2
0
mirror of https://github.com/AxioDL/metaforce.git synced 2025-12-09 02:27:43 +00:00

Blender 2.8 refactor

This commit is contained in:
Jack Andersen
2019-05-07 17:47:34 -10:00
parent 8b1b674a7d
commit 5c59acddf2
48 changed files with 1966 additions and 3460 deletions

View File

@@ -16,6 +16,7 @@
#include "logvisor/logvisor.hpp"
#include "hecl/Blender/Connection.hpp"
#include "hecl/SteamFinder.hpp"
#include "MeshOptimizer.hpp"
#if _WIN32
#include <io.h>
@@ -46,7 +47,7 @@ Token SharedBlenderToken;
#ifdef __APPLE__
#define DEFAULT_BLENDER_BIN "/Applications/Blender.app/Contents/MacOS/blender"
#else
#define DEFAULT_BLENDER_BIN "blender"
#define DEFAULT_BLENDER_BIN "blender-2.8"
#endif
extern "C" uint8_t HECL_BLENDERSHELL[];
@@ -500,16 +501,6 @@ Connection::Connection(int verbosityLevel) {
}
_writeStr("ACK");
_readStr(lineBuf, 7);
if (!strcmp(lineBuf, "SLERP0"))
m_hasSlerp = false;
else if (!strcmp(lineBuf, "SLERP1"))
m_hasSlerp = true;
else {
_closePipe();
BlenderLog.report(logvisor::Fatal, "read '%s' from blender; expected 'SLERP(0|1)'", lineBuf);
}
break;
}
#else
@@ -524,6 +515,8 @@ void Vector3f::read(Connection& conn) { conn._readBuf(&val, 12); }
void Vector4f::read(Connection& conn) { conn._readBuf(&val, 16); }
void Matrix4f::read(Connection& conn) { conn._readBuf(&val, 64); }
void Index::read(Connection& conn) { conn._readBuf(&val, 4); }
void Float::read(Connection& conn) { conn._readBuf(&val, 4); }
void Boolean::read(Connection& conn) { conn._readBuf(&val, 1); }
std::streambuf::int_type PyOutStream::StreamBuf::overflow(int_type ch) {
if (!m_parent.m_parent || !m_parent.m_parent->m_lock)
@@ -755,10 +748,11 @@ void PyOutStream::AABBToBMesh(const atVec3f& min, const atVec3f& max) {
void PyOutStream::centerView() {
*this << "for obj in bpy.context.scene.objects:\n"
" if obj.type == 'CAMERA' or obj.type == 'LAMP':\n"
" obj.hide = True\n"
" if obj.type == 'CAMERA' or obj.type == 'LIGHT':\n"
" obj.hide_set(True)\n"
"\n"
"bpy.context.user_preferences.view.smooth_view = 0\n"
"old_smooth_view = bpy.context.preferences.view.smooth_view\n"
"bpy.context.preferences.view.smooth_view = 0\n"
"for window in bpy.context.window_manager.windows:\n"
" screen = window.screen\n"
" for area in screen.areas:\n"
@@ -769,10 +763,11 @@ void PyOutStream::centerView() {
"area, 'region': region}\n"
" bpy.ops.view3d.view_all(override)\n"
" break\n"
"bpy.context.preferences.view.smooth_view = old_smooth_view\n"
"\n"
"for obj in bpy.context.scene.objects:\n"
" if obj.type == 'CAMERA' or obj.type == 'LAMP':\n"
" obj.hide = False\n";
" if obj.type == 'CAMERA' or obj.type == 'LIGHT':\n"
" obj.hide_set(True)\n";
}
ANIMOutStream::ANIMOutStream(Connection* parent) : m_parent(parent) {
@@ -821,118 +816,65 @@ void ANIMOutStream::write(unsigned frame, float val) {
BlenderLog.report(logvisor::Fatal, "ANIMOutStream keyCount overflow");
}
Mesh::SkinBind::SkinBind(Connection& conn) { conn._readBuf(&boneIdx, 8); }
Mesh::SkinBind::SkinBind(Connection& conn) {
vg_idx = Index(conn).val;
weight = Float(conn).val;
}
void Mesh::normalizeSkinBinds() {
for (std::vector<SkinBind>& skin : skins) {
for (auto& skin : skins) {
float accum = 0.f;
for (const SkinBind& bind : skin)
accum += bind.weight;
if (bind)
accum += bind.weight;
if (accum > FLT_EPSILON) {
for (SkinBind& bind : skin)
bind.weight /= accum;
if (bind)
bind.weight /= accum;
}
}
}
Mesh::Mesh(Connection& conn, HMDLTopology topologyIn, int skinSlotCount, SurfProgFunc& surfProg)
Mesh::Mesh(Connection& conn, HMDLTopology topologyIn, int skinSlotCount, bool useLuvs)
: topology(topologyIn), sceneXf(conn), aabbMin(conn), aabbMax(conn) {
uint32_t matSetCount;
conn._readBuf(&matSetCount, 4);
materialSets.reserve(matSetCount);
for (uint32_t i = 0; i < matSetCount; ++i) {
Index matSetCount(conn);
materialSets.reserve(matSetCount.val);
for (uint32_t i = 0; i < matSetCount.val; ++i) {
materialSets.emplace_back();
std::vector<Material>& materials = materialSets.back();
uint32_t matCount;
conn._readBuf(&matCount, 4);
materials.reserve(matCount);
for (uint32_t i = 0; i < matCount; ++i)
Index matCount(conn);
materials.reserve(matCount.val);
for (uint32_t j = 0; j < matCount.val; ++j)
materials.emplace_back(conn);
}
uint32_t count;
conn._readBuf(&count, 4);
pos.reserve(count);
for (uint32_t i = 0; i < count; ++i)
pos.emplace_back(conn);
MeshOptimizer opt(conn, materialSets[0], useLuvs);
opt.optimize(*this, skinSlotCount);
conn._readBuf(&count, 4);
norm.reserve(count);
for (uint32_t i = 0; i < count; ++i)
norm.emplace_back(conn);
conn._readBuf(&colorLayerCount, 4);
if (colorLayerCount > 4)
LogModule.report(logvisor::Fatal, "mesh has %u color-layers; max 4", colorLayerCount);
conn._readBuf(&count, 4);
color.reserve(count);
for (uint32_t i = 0; i < count; ++i)
color.emplace_back(conn);
conn._readBuf(&uvLayerCount, 4);
if (uvLayerCount > 8)
LogModule.report(logvisor::Fatal, "mesh has %u UV-layers; max 8", uvLayerCount);
conn._readBuf(&count, 4);
uv.reserve(count);
for (uint32_t i = 0; i < count; ++i)
uv.emplace_back(conn);
conn._readBuf(&luvLayerCount, 4);
if (luvLayerCount > 1)
LogModule.report(logvisor::Fatal, "mesh has %u LUV-layers; max 1", luvLayerCount);
conn._readBuf(&count, 4);
luv.reserve(count);
for (uint32_t i = 0; i < count; ++i)
luv.emplace_back(conn);
conn._readBuf(&count, 4);
boneNames.reserve(count);
Index count(conn);
boneNames.reserve(count.val);
for (uint32_t i = 0; i < count; ++i) {
char name[128];
conn._readStr(name, 128);
boneNames.emplace_back(name);
}
conn._readBuf(&count, 4);
skins.reserve(count);
for (uint32_t i = 0; i < count; ++i) {
skins.emplace_back();
std::vector<SkinBind>& binds = skins.back();
uint32_t bindCount;
conn._readBuf(&bindCount, 4);
binds.reserve(bindCount);
for (uint32_t j = 0; j < bindCount; ++j)
binds.emplace_back(conn);
}
normalizeSkinBinds();
/* Assume 16 islands per material for reserve */
if (materialSets.size())
surfaces.reserve(materialSets.front().size() * 16);
uint8_t isSurf;
conn._readBuf(&isSurf, 1);
int prog = 0;
while (isSurf) {
surfaces.emplace_back(conn, *this, skinSlotCount);
surfProg(++prog);
conn._readBuf(&isSurf, 1);
}
if (boneNames.size())
for (Surface& s : surfaces)
s.skinBankIdx = skinBanks.addSurface(*this, s, skinSlotCount);
/* Custom properties */
uint32_t propCount;
conn._readBuf(&propCount, 4);
Index propCount(conn);
std::string keyBuf;
std::string valBuf;
for (uint32_t i = 0; i < propCount; ++i) {
uint32_t kLen;
conn._readBuf(&kLen, 4);
keyBuf.assign(kLen, '\0');
conn._readBuf(&keyBuf[0], kLen);
for (uint32_t i = 0; i < propCount.val; ++i) {
Index kLen(conn);
keyBuf.assign(kLen.val, '\0');
conn._readBuf(&keyBuf[0], kLen.val);
uint32_t vLen;
conn._readBuf(&vLen, 4);
valBuf.assign(vLen, '\0');
conn._readBuf(&valBuf[0], vLen);
Index vLen(conn);
valBuf.assign(vLen.val, '\0');
conn._readBuf(&valBuf[0], vLen.val);
customProps[keyBuf] = valBuf;
}
@@ -991,28 +933,58 @@ Mesh Mesh::getContiguousSkinningVersion() const {
return newMesh;
}
template <typename T>
static T SwapFourCC(T fcc) {
return T(hecl::SBig(std::underlying_type_t<T>(fcc)));
}
Material::PASS::PASS(Connection& conn) {
conn._readBuf(&type, 4);
type = SwapFourCC(type);
uint32_t bufSz;
conn._readBuf(&bufSz, 4);
std::string readStr(bufSz, ' ');
conn._readBuf(&readStr[0], bufSz);
SystemStringConv absolute(readStr);
SystemString relative =
conn.getBlendPath().getProject().getProjectRootPath().getProjectRelativeFromAbsolute(absolute.sys_str());
tex.assign(conn.getBlendPath().getProject().getProjectWorkingPath(), relative);
conn._readBuf(&source, 1);
conn._readBuf(&uvAnimType, 1);
uint32_t argCount;
conn._readBuf(&argCount, 4);
for (uint32_t i = 0; i < argCount; ++i)
conn._readBuf(&uvAnimParms[i], 4);
conn._readBuf(&alpha, 1);
}
Material::CLR::CLR(Connection& conn) {
conn._readBuf(&type, 4);
type = SwapFourCC(type);
color.read(conn);
}
Material::Material(Connection& conn) {
uint32_t bufSz;
conn._readBuf(&bufSz, 4);
name.assign(bufSz, ' ');
conn._readBuf(&name[0], bufSz);
conn._readBuf(&bufSz, 4);
source.assign(bufSz, ' ');
conn._readBuf(&source[0], bufSz);
conn._readBuf(&passIndex, 4);
conn._readBuf(&shaderType, 4);
shaderType = SwapFourCC(shaderType);
uint32_t texCount;
conn._readBuf(&texCount, 4);
texs.reserve(texCount);
for (uint32_t i = 0; i < texCount; ++i) {
conn._readBuf(&bufSz, 4);
std::string readStr(bufSz, ' ');
conn._readBuf(&readStr[0], bufSz);
SystemStringConv absolute(readStr);
SystemString relative =
conn.getBlendPath().getProject().getProjectRootPath().getProjectRelativeFromAbsolute(absolute.sys_str());
texs.emplace_back(conn.getBlendPath().getProject().getProjectWorkingPath(), relative);
uint32_t chunkCount;
conn._readBuf(&chunkCount, 4);
chunks.reserve(chunkCount);
for (uint32_t i = 0; i < chunkCount; ++i) {
ChunkType type;
conn._readBuf(&type, 4);
type = SwapFourCC(type);
chunks.push_back(Chunk::Build(type, conn));
}
uint32_t iPropCount;
@@ -1028,36 +1000,7 @@ Material::Material(Connection& conn) {
iprops[readStr] = val;
}
conn._readBuf(&transparent, 1);
}
Mesh::Surface::Surface(Connection& conn, Mesh& parent, int skinSlotCount)
: centroid(conn), materialIdx(conn), aabbMin(conn), aabbMax(conn), reflectionNormal(conn) {
uint32_t countEstimate;
conn._readBuf(&countEstimate, 4);
verts.reserve(countEstimate);
uint8_t isVert;
conn._readBuf(&isVert, 1);
while (isVert) {
verts.emplace_back(conn, parent);
conn._readBuf(&isVert, 1);
}
if (parent.boneNames.size())
skinBankIdx = parent.skinBanks.addSurface(parent, *this, skinSlotCount);
}
Mesh::Surface::Vert::Vert(Connection& conn, const Mesh& parent) {
conn._readBuf(&iPos, 4);
if (iPos == 0xffffffff)
return;
conn._readBuf(&iNorm, 4);
for (uint32_t i = 0; i < parent.colorLayerCount; ++i)
conn._readBuf(&iColor[i], 4);
for (uint32_t i = 0; i < parent.uvLayerCount; ++i)
conn._readBuf(&iUv[i], 4);
conn._readBuf(&iSkin, 4);
conn._readBuf(&blendMode, 4);
}
bool Mesh::Surface::Vert::operator==(const Vert& other) const {
@@ -1087,26 +1030,21 @@ void Mesh::SkinBanks::Bank::addSkins(const Mesh& parent, const std::vector<uint3
for (uint32_t sidx : skinIdxs) {
m_skinIdxs.push_back(sidx);
for (const SkinBind& bind : parent.skins[sidx]) {
if (!bind)
break;
bool found = false;
for (uint32_t bidx : m_boneIdxs) {
if (bidx == bind.boneIdx) {
if (bidx == bind.vg_idx) {
found = true;
break;
}
}
if (!found)
m_boneIdxs.push_back(bind.boneIdx);
m_boneIdxs.push_back(bind.vg_idx);
}
}
}
size_t Mesh::SkinBanks::Bank::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<Mesh::SkinBanks::Bank>::iterator Mesh::SkinBanks::addSkinBank(int skinSlotCount) {
banks.emplace_back();
if (skinSlotCount > 0)
@@ -1631,32 +1569,28 @@ const char* DataStream::MeshOutputModeString(HMDLTopology topology) {
return STRS[int(topology)];
}
Mesh DataStream::compileMesh(HMDLTopology topology, int skinSlotCount, Mesh::SurfProgFunc surfProg) {
Mesh DataStream::compileMesh(HMDLTopology topology, int skinSlotCount) {
if (m_parent->getBlendType() != BlendType::Mesh)
BlenderLog.report(logvisor::Fatal, _SYS_STR("%s is not a MESH blend"),
m_parent->getBlendPath().getAbsolutePath().data());
char req[128];
snprintf(req, 128, "MESHCOMPILE %s %d", MeshOutputModeString(topology), skinSlotCount);
m_parent->_writeStr(req);
m_parent->_writeStr("MESHCOMPILE");
char readBuf[256];
m_parent->_readStr(readBuf, 256);
if (strcmp(readBuf, "OK"))
BlenderLog.report(logvisor::Fatal, "unable to cook mesh: %s", readBuf);
return Mesh(*m_parent, topology, skinSlotCount, surfProg);
return Mesh(*m_parent, topology, skinSlotCount);
}
Mesh DataStream::compileMesh(std::string_view name, HMDLTopology topology, int skinSlotCount, bool useLuv,
Mesh::SurfProgFunc surfProg) {
Mesh DataStream::compileMesh(std::string_view name, HMDLTopology topology, int skinSlotCount, bool useLuv) {
if (m_parent->getBlendType() != BlendType::Area)
BlenderLog.report(logvisor::Fatal, _SYS_STR("%s is not an AREA blend"),
m_parent->getBlendPath().getAbsolutePath().data());
char req[128];
snprintf(req, 128, "MESHCOMPILENAME %s %s %d %d", name.data(), MeshOutputModeString(topology), skinSlotCount,
int(useLuv));
snprintf(req, 128, "MESHCOMPILENAME %s %d", name.data(), int(useLuv));
m_parent->_writeStr(req);
char readBuf[256];
@@ -1664,7 +1598,7 @@ Mesh DataStream::compileMesh(std::string_view name, HMDLTopology topology, int s
if (strcmp(readBuf, "OK"))
BlenderLog.report(logvisor::Fatal, "unable to cook mesh '%s': %s", name.data(), readBuf);
return Mesh(*m_parent, topology, skinSlotCount, surfProg);
return Mesh(*m_parent, topology, skinSlotCount, useLuv);
}
ColMesh DataStream::compileColMesh(std::string_view name) {
@@ -1710,24 +1644,6 @@ std::vector<ColMesh> DataStream::compileColMeshes() {
return ret;
}
Mesh DataStream::compileAllMeshes(HMDLTopology topology, int skinSlotCount, float maxOctantLength,
Mesh::SurfProgFunc surfProg) {
if (m_parent->getBlendType() != BlendType::Area)
BlenderLog.report(logvisor::Fatal, _SYS_STR("%s is not an AREA blend"),
m_parent->getBlendPath().getAbsolutePath().data());
char req[128];
snprintf(req, 128, "MESHCOMPILEALL %s %d %f", MeshOutputModeString(topology), skinSlotCount, maxOctantLength);
m_parent->_writeStr(req);
char readBuf[256];
m_parent->_readStr(readBuf, 256);
if (strcmp(readBuf, "OK"))
BlenderLog.report(logvisor::Fatal, "unable to cook all meshes: %s", readBuf);
return Mesh(*m_parent, topology, skinSlotCount, surfProg);
}
std::vector<Light> DataStream::compileLights() {
if (m_parent->getBlendType() != BlendType::Area)
BlenderLog.report(logvisor::Fatal, _SYS_STR("%s is not an AREA blend"),