diff --git a/hecl/blender/BlenderConnection.cpp b/hecl/blender/BlenderConnection.cpp index cacc55afb..11e63354f 100644 --- a/hecl/blender/BlenderConnection.cpp +++ b/hecl/blender/BlenderConnection.cpp @@ -871,6 +871,54 @@ uint32_t BlenderConnection::DataStream::Mesh::SkinBanks::addSurface return uint32_t(-1); } +BlenderConnection::DataStream::ColMesh::ColMesh(BlenderConnection& conn) +: sceneXf(conn), aabbMin(conn), aabbMax(conn) +{ + uint32_t matCount; + conn._readBuf(&matCount, 4); + materials.reserve(matCount); + for (uint32_t i=0 ; im_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, "MESHCOMPILENAMECOLLISION %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 cook collision mesh '%s': %s", name.c_str(), readBuf); + + return ColMesh(*m_parent); +} + BlenderConnection::DataStream::Mesh BlenderConnection::DataStream::compileAllMeshes(HMDLTopology topology, int skinSlotCount, diff --git a/hecl/blender/BlenderConnection.hpp b/hecl/blender/BlenderConnection.hpp index f613549b5..e74d84912 100644 --- a/hecl/blender/BlenderConnection.hpp +++ b/hecl/blender/BlenderConnection.hpp @@ -371,6 +371,8 @@ public: operator const uint32_t&() const {return val;} }; + static atVec3f MtxVecMul4RM(const Matrix4f& mtx, const Vector3f& vec); + /** Intermediate mesh representation prepared by blender from a single mesh object */ struct Mesh { @@ -517,7 +519,48 @@ public: /** Prepares mesh representation for indexed access on modern APIs. * Mesh must remain resident for accessing reference members */ - HMDLBuffers getHMDLBuffers() const; + HMDLBuffers getHMDLBuffers(bool absoluteCoords) const; + }; + + /** Intermediate collision mesh representation prepared by blender from a single mesh object */ + struct ColMesh + { + /* Object transform in scene */ + Matrix4f sceneXf; + + /* Cumulative AABB */ + Vector3f aabbMin; + Vector3f aabbMax; + + /** HECL source and metadata of each material */ + struct Material + { + std::string name; + uint32_t type; + bool fireThrough; + Material(BlenderConnection& conn); + }; + std::vector materials; + + std::vector verts; + + struct Edge + { + uint32_t verts[2]; + bool seam; + Edge(BlenderConnection& conn); + }; + std::vector edges; + + struct Triangle + { + uint32_t edges[3]; + uint32_t matIdx; + Triangle(BlenderConnection& conn); + }; + std::vector trianges; + + ColMesh(BlenderConnection& conn); }; @@ -536,6 +579,9 @@ public: Mesh compileMesh(const std::string& name, HMDLTopology topology, int skinSlotCount=10, Mesh::SurfProgFunc surfProg=[](int){}); + /** Compile collision mesh by name (AREA blends only) */ + ColMesh compileColMesh(const std::string& name); + /** Compile all meshes into one (AREA blends only) */ Mesh compileAllMeshes(HMDLTopology topology, int skinSlotCount=10, float maxOctantLength=5.0, Mesh::SurfProgFunc surfProg=[](int){}); diff --git a/hecl/blender/HMDL.cpp b/hecl/blender/HMDL.cpp index 3147b62f1..5535e4958 100644 --- a/hecl/blender/HMDL.cpp +++ b/hecl/blender/HMDL.cpp @@ -3,7 +3,16 @@ namespace hecl { -HMDLBuffers BlenderConnection::DataStream::Mesh::getHMDLBuffers() const +atVec3f BlenderConnection::DataStream::MtxVecMul4RM(const Matrix4f& mtx, const Vector3f& vec) +{ + atVec3f res; + res.vec[0] = mtx[0].vec[0] * vec.val.vec[0] + mtx[0].vec[1] * vec.val.vec[1] + mtx[0].vec[2] * vec.val.vec[2] + mtx[0].vec[3]; + res.vec[1] = mtx[1].vec[0] * vec.val.vec[0] + mtx[1].vec[1] * vec.val.vec[1] + mtx[1].vec[2] * vec.val.vec[2] + mtx[1].vec[3]; + res.vec[2] = mtx[2].vec[0] * vec.val.vec[0] + mtx[2].vec[1] * vec.val.vec[1] + mtx[2].vec[2] * vec.val.vec[2] + mtx[2].vec[3]; + return res; +} + +HMDLBuffers BlenderConnection::DataStream::Mesh::getHMDLBuffers(bool absoluteCoords) const { /* If skinned, compute max weight vec count */ size_t weightCount = 0; @@ -75,7 +84,13 @@ HMDLBuffers BlenderConnection::DataStream::Mesh::getHMDLBuffers() const const Surface& s = *sv.first; const Surface::Vert& v = *sv.second; - vboW.writeVec3fLittle(pos[v.iPos]); + if (absoluteCoords) + { + atVec3f preXfPos = MtxVecMul4RM(sceneXf, pos[v.iPos]); + vboW.writeVec3fLittle(preXfPos); + } + else + vboW.writeVec3fLittle(pos[v.iPos]); vboW.writeVec3fLittle(norm[v.iNorm]); for (size_t i=0 ; i