From 51822eec945ad64a9582c0cd7a18c49881098391 Mon Sep 17 00:00:00 2001 From: Jack Andersen Date: Thu, 7 Apr 2016 17:34:21 -1000 Subject: [PATCH] Additional BlenderConnection interfaces --- hecl/blender/BlenderConnection.cpp | 222 +++++++++++++++++++++++++++++ hecl/blender/BlenderConnection.hpp | 167 ++-------------------- hecl/blender/hecl_blendershell.py | 21 +++ 3 files changed, 257 insertions(+), 153 deletions(-) diff --git a/hecl/blender/BlenderConnection.cpp b/hecl/blender/BlenderConnection.cpp index b89704ff8..15f8c7ebb 100644 --- a/hecl/blender/BlenderConnection.cpp +++ b/hecl/blender/BlenderConnection.cpp @@ -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 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 ret; + + uint32_t armCount; + m_parent->_readBuf(&armCount, 4); + ret.reserve(armCount); + for (uint32_t i=0 ; i_readBuf(&bufSz, 4); + name.assign(bufSz, ' '); + m_parent->_readBuf(&name[0], bufSz); + } + + return ret; +} + +std::vector 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 ret; + + uint32_t actCount; + m_parent->_readBuf(&actCount, 4); + ret.reserve(actCount); + for (uint32_t i=0 ; i_readBuf(&bufSz, 4); + name.assign(bufSz, ' '); + m_parent->_readBuf(&name[0], bufSz); + } + + return ret; +} + +std::unordered_map +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 ret; + + uint32_t boneCount; + m_parent->_readBuf(&boneCount, 4); + ret.reserve(boneCount); + for (uint32_t i=0 ; i_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(matOut[i]).vec[3] = 0.f; + } + + ret.emplace(std::make_pair(std::move(name), std::move(matOut))); + } + + return ret; + +} + void BlenderConnection::quitBlender() { _writeLine("QUIT"); diff --git a/hecl/blender/BlenderConnection.hpp b/hecl/blender/BlenderConnection.hpp index bcf427d36..860a4307c 100644 --- a/hecl/blender/BlenderConnection.hpp +++ b/hecl/blender/BlenderConnection.hpp @@ -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 getArmatureNames(); + std::vector 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 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 ret; - - uint32_t armCount; - m_parent->_readBuf(&armCount, 4); - ret.reserve(armCount); - for (uint32_t i=0 ; i_readBuf(&bufSz, 4); - name.assign(bufSz, ' '); - m_parent->_readBuf(&name[0], bufSz); - } - - return ret; - } - - std::vector 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 ret; - - uint32_t actCount; - m_parent->_readBuf(&actCount, 4); - ret.reserve(actCount); - for (uint32_t i=0 ; i_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 getBoneMatrices(const std::string& name); }; DataStream beginData() { diff --git a/hecl/blender/hecl_blendershell.py b/hecl/blender/hecl_blendershell.py index 58175d5fe..1f20bf6e7 100644 --- a/hecl/blender/hecl_blendershell.py +++ b/hecl/blender/hecl_blendershell.py @@ -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: