Additional BlenderConnection interfaces

This commit is contained in:
Jack Andersen 2016-04-07 17:34:21 -10:00
parent 761be432be
commit 51822eec94
3 changed files with 257 additions and 153 deletions

View File

@ -369,6 +369,30 @@ BlenderConnection::~BlenderConnection()
_closePipe();
}
std::streambuf::int_type
BlenderConnection::PyOutStream::StreamBuf::overflow(int_type ch)
{
if (!m_parent.m_parent || !m_parent.m_parent->m_lock)
BlenderLog.report(logvisor::Fatal, "lock not held for PyOutStream writing");
if (ch != traits_type::eof() && ch != '\n' && ch != '\0')
{
m_lineBuf += char_type(ch);
return ch;
}
//printf("FLUSHING %s\n", m_lineBuf.c_str());
m_parent.m_parent->_writeLine(m_lineBuf.c_str());
char readBuf[16];
m_parent.m_parent->_readLine(readBuf, 16);
if (strcmp(readBuf, "OK"))
{
if (m_deleteOnError)
m_parent.m_parent->deleteBlend();
BlenderLog.report(logvisor::Fatal, "error sending '%s' to blender", m_lineBuf.c_str());
}
m_lineBuf.clear();
return ch;
}
static const char* BlendTypeStrs[] =
{
"NONE",
@ -956,6 +980,204 @@ BlenderConnection::DataStream::Actor::Action::Channel::Key::Key(BlenderConnectio
scale.read(conn);
}
BlenderConnection::DataStream::Mesh
BlenderConnection::DataStream::compileMesh(HMDLTopology topology,
int skinSlotCount,
Mesh::SurfProgFunc surfProg)
{
if (m_parent->m_loadedType != BlendType::Mesh)
BlenderLog.report(logvisor::Fatal, _S("%s is not a MESH blend"),
m_parent->m_loadedBlend.getAbsolutePath().c_str());
char req[128];
snprintf(req, 128, "MESHCOMPILE %s %d",
MeshOutputModeString(topology), skinSlotCount);
m_parent->_writeLine(req);
char readBuf[256];
m_parent->_readLine(readBuf, 256);
if (strcmp(readBuf, "OK"))
BlenderLog.report(logvisor::Fatal, "unable to cook mesh: %s", readBuf);
return Mesh(*m_parent, topology, skinSlotCount, surfProg);
}
BlenderConnection::DataStream::Mesh
BlenderConnection::DataStream::compileMesh(const std::string& name,
HMDLTopology topology,
int skinSlotCount,
Mesh::SurfProgFunc surfProg)
{
if (m_parent->m_loadedType != BlendType::Area)
BlenderLog.report(logvisor::Fatal, _S("%s is not an AREA blend"),
m_parent->m_loadedBlend.getAbsolutePath().c_str());
char req[128];
snprintf(req, 128, "MESHCOMPILENAME %s %s %d", name.c_str(),
MeshOutputModeString(topology), skinSlotCount);
m_parent->_writeLine(req);
char readBuf[256];
m_parent->_readLine(readBuf, 256);
if (strcmp(readBuf, "OK"))
BlenderLog.report(logvisor::Fatal, "unable to cook mesh '%s': %s", name.c_str(), readBuf);
return Mesh(*m_parent, topology, skinSlotCount, surfProg);
}
BlenderConnection::DataStream::Mesh
BlenderConnection::DataStream::compileAllMeshes(HMDLTopology topology,
int skinSlotCount,
float maxOctantLength,
Mesh::SurfProgFunc surfProg)
{
if (m_parent->m_loadedType != BlendType::Area)
BlenderLog.report(logvisor::Fatal, _S("%s is not an AREA blend"),
m_parent->m_loadedBlend.getAbsolutePath().c_str());
char req[128];
snprintf(req, 128, "MESHCOMPILEALL %s %d %f",
MeshOutputModeString(topology),
skinSlotCount, maxOctantLength);
m_parent->_writeLine(req);
char readBuf[256];
m_parent->_readLine(readBuf, 256);
if (strcmp(readBuf, "OK"))
BlenderLog.report(logvisor::Fatal, "unable to cook all meshes: %s", readBuf);
return Mesh(*m_parent, topology, skinSlotCount, surfProg);
}
BlenderConnection::DataStream::Actor BlenderConnection::DataStream::compileActor()
{
if (m_parent->m_loadedType != BlendType::Actor)
BlenderLog.report(logvisor::Fatal, _S("%s is not an ACTOR blend"),
m_parent->m_loadedBlend.getAbsolutePath().c_str());
m_parent->_writeLine("ACTORCOMPILE");
char readBuf[256];
m_parent->_readLine(readBuf, 256);
if (strcmp(readBuf, "OK"))
BlenderLog.report(logvisor::Fatal, "unable to compile actor: %s", readBuf);
return Actor(*m_parent);
}
std::vector<std::string> BlenderConnection::DataStream::getArmatureNames()
{
if (m_parent->m_loadedType != BlendType::Actor)
BlenderLog.report(logvisor::Fatal, _S("%s is not an ACTOR blend"),
m_parent->m_loadedBlend.getAbsolutePath().c_str());
m_parent->_writeLine("GETARMATURENAMES");
char readBuf[256];
m_parent->_readLine(readBuf, 256);
if (strcmp(readBuf, "OK"))
BlenderLog.report(logvisor::Fatal, "unable to get armatures of actor: %s", readBuf);
std::vector<std::string> ret;
uint32_t armCount;
m_parent->_readBuf(&armCount, 4);
ret.reserve(armCount);
for (uint32_t i=0 ; i<armCount ; ++i)
{
ret.emplace_back();
std::string& name = ret.back();
uint32_t bufSz;
m_parent->_readBuf(&bufSz, 4);
name.assign(bufSz, ' ');
m_parent->_readBuf(&name[0], bufSz);
}
return ret;
}
std::vector<std::string> BlenderConnection::DataStream::getActionNames()
{
if (m_parent->m_loadedType != BlendType::Actor)
BlenderLog.report(logvisor::Fatal, _S("%s is not an ACTOR blend"),
m_parent->m_loadedBlend.getAbsolutePath().c_str());
m_parent->_writeLine("GETACTIONNAMES");
char readBuf[256];
m_parent->_readLine(readBuf, 256);
if (strcmp(readBuf, "OK"))
BlenderLog.report(logvisor::Fatal, "unable to get actions of actor: %s", readBuf);
std::vector<std::string> ret;
uint32_t actCount;
m_parent->_readBuf(&actCount, 4);
ret.reserve(actCount);
for (uint32_t i=0 ; i<actCount ; ++i)
{
ret.emplace_back();
std::string& name = ret.back();
uint32_t bufSz;
m_parent->_readBuf(&bufSz, 4);
name.assign(bufSz, ' ');
m_parent->_readBuf(&name[0], bufSz);
}
return ret;
}
std::unordered_map<std::string, BlenderConnection::DataStream::Matrix3f>
BlenderConnection::DataStream::getBoneMatrices(const std::string& name)
{
if (name.empty())
return {};
if (m_parent->m_loadedType != BlendType::Actor)
BlenderLog.report(logvisor::Fatal, _S("%s is not an ACTOR blend"),
m_parent->m_loadedBlend.getAbsolutePath().c_str());
char req[128];
snprintf(req, 128, "GETBONEMATRICES %s", name.c_str());
m_parent->_writeLine(req);
char readBuf[256];
m_parent->_readLine(readBuf, 256);
if (strcmp(readBuf, "OK"))
BlenderLog.report(logvisor::Fatal, "unable to get matrices of armature: %s", readBuf);
std::unordered_map<std::string, Matrix3f> ret;
uint32_t boneCount;
m_parent->_readBuf(&boneCount, 4);
ret.reserve(boneCount);
for (uint32_t i=0 ; i<boneCount ; ++i)
{
std::string name;
uint32_t bufSz;
m_parent->_readBuf(&bufSz, 4);
name.assign(bufSz, ' ');
m_parent->_readBuf(&name[0], bufSz);
Matrix3f matOut;
for (int i=0 ; i<3 ; ++i)
{
for (int j=0 ; j<3 ; ++j)
{
float val;
m_parent->_readBuf(&val, 4);
matOut[i].vec[j] = val;
}
reinterpret_cast<atVec4f&>(matOut[i]).vec[3] = 0.f;
}
ret.emplace(std::make_pair(std::move(name), std::move(matOut)));
}
return ret;
}
void BlenderConnection::quitBlender()
{
_writeLine("QUIT");

View File

@ -97,28 +97,7 @@ public:
: m_parent(parent), m_deleteOnError(deleteOnError) {}
StreamBuf(const StreamBuf& other) = delete;
StreamBuf(StreamBuf&& other) = default;
int_type overflow(int_type ch)
{
if (!m_parent.m_parent || !m_parent.m_parent->m_lock)
BlenderLog.report(logvisor::Fatal, "lock not held for PyOutStream writing");
if (ch != traits_type::eof() && ch != '\n' && ch != '\0')
{
m_lineBuf += char_type(ch);
return ch;
}
//printf("FLUSHING %s\n", m_lineBuf.c_str());
m_parent.m_parent->_writeLine(m_lineBuf.c_str());
char readBuf[16];
m_parent.m_parent->_readLine(readBuf, 16);
if (strcmp(readBuf, "OK"))
{
if (m_deleteOnError)
m_parent.m_parent->deleteBlend();
BlenderLog.report(logvisor::Fatal, "error sending '%s' to blender", m_lineBuf.c_str());
}
m_lineBuf.clear();
return ch;
}
int_type overflow(int_type ch);
} m_sbuf;
PyOutStream(BlenderConnection* parent, bool deleteOnError)
: std::ostream(&m_sbuf),
@ -532,67 +511,15 @@ public:
/** Compile mesh by context (MESH blends only) */
Mesh compileMesh(HMDLTopology topology, int skinSlotCount=10,
Mesh::SurfProgFunc surfProg=[](int){})
{
if (m_parent->m_loadedType != BlendType::Mesh)
BlenderLog.report(logvisor::Fatal, _S("%s is not a MESH blend"),
m_parent->m_loadedBlend.getAbsolutePath().c_str());
char req[128];
snprintf(req, 128, "MESHCOMPILE %s %d",
MeshOutputModeString(topology), skinSlotCount);
m_parent->_writeLine(req);
char readBuf[256];
m_parent->_readLine(readBuf, 256);
if (strcmp(readBuf, "OK"))
BlenderLog.report(logvisor::Fatal, "unable to cook mesh: %s", readBuf);
return Mesh(*m_parent, topology, skinSlotCount, surfProg);
}
Mesh::SurfProgFunc surfProg=[](int){});
/** Compile mesh by name (AREA blends only) */
Mesh compileMesh(const std::string& name, HMDLTopology topology, int skinSlotCount=10,
Mesh::SurfProgFunc surfProg=[](int){})
{
if (m_parent->m_loadedType != BlendType::Area)
BlenderLog.report(logvisor::Fatal, _S("%s is not an AREA blend"),
m_parent->m_loadedBlend.getAbsolutePath().c_str());
char req[128];
snprintf(req, 128, "MESHCOMPILENAME %s %s %d", name.c_str(),
MeshOutputModeString(topology), skinSlotCount);
m_parent->_writeLine(req);
char readBuf[256];
m_parent->_readLine(readBuf, 256);
if (strcmp(readBuf, "OK"))
BlenderLog.report(logvisor::Fatal, "unable to cook mesh '%s': %s", name.c_str(), readBuf);
return Mesh(*m_parent, topology, skinSlotCount, surfProg);
}
Mesh::SurfProgFunc surfProg=[](int){});
/** Compile all meshes into one (AREA blends only) */
Mesh compileAllMeshes(HMDLTopology topology, int skinSlotCount=10, float maxOctantLength=5.0,
Mesh::SurfProgFunc surfProg=[](int){})
{
if (m_parent->m_loadedType != BlendType::Area)
BlenderLog.report(logvisor::Fatal, _S("%s is not an AREA blend"),
m_parent->m_loadedBlend.getAbsolutePath().c_str());
char req[128];
snprintf(req, 128, "MESHCOMPILEALL %s %d %f",
MeshOutputModeString(topology),
skinSlotCount, maxOctantLength);
m_parent->_writeLine(req);
char readBuf[256];
m_parent->_readLine(readBuf, 256);
if (strcmp(readBuf, "OK"))
BlenderLog.report(logvisor::Fatal, "unable to cook all meshes: %s", readBuf);
return Mesh(*m_parent, topology, skinSlotCount, surfProg);
}
Mesh::SurfProgFunc surfProg=[](int){});
/** Intermediate actor representation prepared by blender from a single HECL actor blend */
struct Actor
@ -681,83 +608,17 @@ public:
Actor(BlenderConnection& conn);
};
Actor compileActor()
Actor compileActor();
std::vector<std::string> getArmatureNames();
std::vector<std::string> getActionNames();
struct Matrix3f
{
if (m_parent->m_loadedType != BlendType::Actor)
BlenderLog.report(logvisor::Fatal, _S("%s is not an ACTOR blend"),
m_parent->m_loadedBlend.getAbsolutePath().c_str());
m_parent->_writeLine("ACTORCOMPILE");
char readBuf[256];
m_parent->_readLine(readBuf, 256);
if (strcmp(readBuf, "OK"))
BlenderLog.report(logvisor::Fatal, "unable to compile actor: %s", readBuf);
return Actor(*m_parent);
}
std::vector<std::string> getArmatureNames()
{
if (m_parent->m_loadedType != BlendType::Actor)
BlenderLog.report(logvisor::Fatal, _S("%s is not an ACTOR blend"),
m_parent->m_loadedBlend.getAbsolutePath().c_str());
m_parent->_writeLine("GETARMATURENAMES");
char readBuf[256];
m_parent->_readLine(readBuf, 256);
if (strcmp(readBuf, "OK"))
BlenderLog.report(logvisor::Fatal, "unable to get armatures of actor: %s", readBuf);
std::vector<std::string> ret;
uint32_t armCount;
m_parent->_readBuf(&armCount, 4);
ret.reserve(armCount);
for (uint32_t i=0 ; i<armCount ; ++i)
{
ret.emplace_back();
std::string& name = ret.back();
uint32_t bufSz;
m_parent->_readBuf(&bufSz, 4);
name.assign(bufSz, ' ');
m_parent->_readBuf(&name[0], bufSz);
}
return ret;
}
std::vector<std::string> getActionNames()
{
if (m_parent->m_loadedType != BlendType::Actor)
BlenderLog.report(logvisor::Fatal, _S("%s is not an ACTOR blend"),
m_parent->m_loadedBlend.getAbsolutePath().c_str());
m_parent->_writeLine("GETACTIONNAMES");
char readBuf[256];
m_parent->_readLine(readBuf, 256);
if (strcmp(readBuf, "OK"))
BlenderLog.report(logvisor::Fatal, "unable to get actions of actor: %s", readBuf);
std::vector<std::string> ret;
uint32_t actCount;
m_parent->_readBuf(&actCount, 4);
ret.reserve(actCount);
for (uint32_t i=0 ; i<actCount ; ++i)
{
ret.emplace_back();
std::string& name = ret.back();
uint32_t bufSz;
m_parent->_readBuf(&bufSz, 4);
name.assign(bufSz, ' ');
m_parent->_readBuf(&name[0], bufSz);
}
return ret;
}
atVec3f m[3];
inline atVec3f& operator[](size_t idx) {return m[idx];}
inline const atVec3f& operator[](size_t idx) const {return m[idx];}
};
std::unordered_map<std::string, Matrix3f> getBoneMatrices(const std::string& name);
};
DataStream beginData()
{

View File

@ -197,6 +197,27 @@ def dataout_loop():
writepipeline(b'OK')
hecl.sact.get_action_names(writepipebuf)
elif cmdargs[0] == 'GETBONEMATRICES':
armName = cmdargs[1]
if armName not in bpy.data.objects:
writepipeline(('armature %s not found' % armName).encode())
continue
armObj = bpy.data.objects[armName]
if armObj.type != 'ARMATURE':
writepipeline(('object %s not an ARMATURE' % armName).encode())
continue
writepipeline(b'OK')
writepipebuf(struct.pack('I', len(armObj.data.bones)))
for bone in armObj.data.bones:
writepipebuf(struct.pack('I', len(bone.name)))
writepipebuf(bone.name.encode())
for r in bone.matrix:
for c in r:
writepipebuf(struct.pack('f', c))
# Command loop
while True: