diff --git a/hecl/blender/BlenderConnection.cpp b/hecl/blender/BlenderConnection.cpp index 3e0bdb614..0c5336e45 100644 --- a/hecl/blender/BlenderConnection.cpp +++ b/hecl/blender/BlenderConnection.cpp @@ -654,7 +654,8 @@ uint32_t BlenderConnection::DataStream::Mesh::SkinBanks::addSurface if (banks.empty()) addSkinBank(skinSlotCount); std::vector toAdd; - toAdd.reserve(skinSlotCount); + if (skinSlotCount > 0) + toAdd.reserve(skinSlotCount); std::vector>::iterator bankIt = banks.begin(); for (;;) { @@ -668,7 +669,7 @@ uint32_t BlenderConnection::DataStream::Mesh::SkinBanks::addSurface if (!VertInBank(bank, v.iSkin) && !VertInBank(toAdd, v.iSkin)) { toAdd.push_back(v.iSkin); - if (bank.size() + toAdd.size() > skinSlotCount) + if (skinSlotCount > 0 && bank.size() + toAdd.size() > skinSlotCount) { toAdd.clear(); done = false; diff --git a/hecl/blender/BlenderConnection.hpp b/hecl/blender/BlenderConnection.hpp index 29a41752b..79e1aa486 100644 --- a/hecl/blender/BlenderConnection.hpp +++ b/hecl/blender/BlenderConnection.hpp @@ -290,16 +290,19 @@ public: { atVec2f val; Vector2f(BlenderConnection& conn) {conn._readBuf(&val, 8);} + operator const atVec2f&() const {return val;} }; struct Vector3f { atVec3f val; Vector3f(BlenderConnection& conn) {conn._readBuf(&val, 12);} + operator const atVec3f&() const {return val;} }; struct Index { uint32_t val; Index(BlenderConnection& conn) {conn._readBuf(&val, 4);} + operator const uint32_t&() const {return val;} }; /* Cumulative AABB */ @@ -370,7 +373,8 @@ public: std::vector>::iterator addSkinBank(int skinSlotCount) { banks.emplace_back(); - banks.back().reserve(skinSlotCount); + if (skinSlotCount > 0) + banks.back().reserve(skinSlotCount); return banks.end() - 1; } uint32_t addSurface(const Surface& surf, int skinSlotCount); diff --git a/hecl/blender/hecl/hmdl/HMDLMesh.py b/hecl/blender/hecl/hmdl/HMDLMesh.py index 3de11d5b9..d7e3abae8 100644 --- a/hecl/blender/hecl/hmdl/HMDLMesh.py +++ b/hecl/blender/hecl/hmdl/HMDLMesh.py @@ -133,6 +133,34 @@ class VertPool: sp = struct.pack('I', self.get_skin_idx(loop.vert)) writebuf(sp) +def sort_faces_by_skin_group(dlay, faces): + faces_out = [] + done_sg = set() + ref_sg = None + while len(faces_out) < len(faces): + for f in faces: + found = False + for v in f.verts: + sg = tuple(sorted(v[dlay].items())) + if sg not in done_sg: + ref_sg = sg + done_sg.add(ref_sg) + found = True + break + if found: + break + + for f in faces: + if f in faces_out: + continue + for v in f.verts: + sg = tuple(sorted(v[dlay].items())) + if sg == ref_sg: + faces_out.append(f) + break + + return faces_out + def recursive_faces_islands(dlay, list_out, rem_list, skin_slot_set, skin_slot_count, face): if face not in rem_list: return [] @@ -140,9 +168,10 @@ def recursive_faces_islands(dlay, list_out, rem_list, skin_slot_set, skin_slot_c if dlay: for v in face.verts: sg = tuple(sorted(v[dlay].items())) - if sg not in skin_slot_set and len(skin_slot_set) == skin_slot_count: - return False - skin_slot_set.add(sg) + if sg not in skin_slot_set: + if skin_slot_count > 0 and len(skin_slot_set) == skin_slot_count: + return False + skin_slot_set.add(sg) list_out.append(face) rem_list.remove(face) @@ -321,5 +350,6 @@ def write_out_surface(writebuf, vert_pool, island_faces, mat_idx): for f in max_sl: island_faces.remove(f) last_loop, next_idx = stripify_primitive(writebuf, vert_pool, max_sl, last_loop, next_idx) + writebuf(struct.pack('B', 0)) diff --git a/hecl/blender/hecl/hmdl/__init__.py b/hecl/blender/hecl/hmdl/__init__.py index b9d44729b..7acbf7968 100644 --- a/hecl/blender/hecl/hmdl/__init__.py +++ b/hecl/blender/hecl/hmdl/__init__.py @@ -166,12 +166,52 @@ def cook(writebuf, mesh_obj, max_skin_banks, max_octant_length=None): if len(bm_master.verts.layers.deform): dlay = bm_master.verts.layers.deform[0] - # Generate island meshes + # Generate material meshes (if opaque) for mat_idx in sorted_material_idxs: + mat = mesh_obj.data.materials[mat_idx] + if mat.game_settings.alpha_blend != 'OPAQUE': + continue mat_faces_rem = [] for face in bm_master.faces: if face.material_index == mat_idx: mat_faces_rem.append(face) + if dlay: + mat_faces_rem = HMDLMesh.sort_faces_by_skin_group(dlay, mat_faces_rem) + while len(mat_faces_rem): + the_list = [] + skin_slot_set = set() + faces = list(mat_faces_rem) + for f in faces: + ret_faces = None + for v in f.verts: + sg = tuple(sorted(v[dlay].items())) + if sg not in skin_slot_set: + if max_skin_banks > 0 and len(skin_slot_set) == max_skin_banks: + ret_faces = False + break + skin_slot_set.add(sg) + + if ret_faces == False: + break + + the_list.append(f) + mat_faces_rem.remove(f) + + writebuf(struct.pack('B', 1)) + HMDLMesh.write_out_surface(writebuf, vert_pool, the_list, mat_idx) + + + # Generate island meshes (if transparent) + for mat_idx in sorted_material_idxs: + mat = mesh_obj.data.materials[mat_idx] + if mat.game_settings.alpha_blend == 'OPAQUE': + continue + mat_faces_rem = [] + for face in bm_master.faces: + if face.material_index == mat_idx: + mat_faces_rem.append(face) + if dlay: + mat_faces_rem = HMDLMesh.sort_faces_by_skin_group(dlay, mat_faces_rem) while len(mat_faces_rem): the_list = [] skin_slot_set = set() diff --git a/hecl/include/HECL/Backend/GX.hpp b/hecl/include/HECL/Backend/GX.hpp index b1efa3a90..74bacd828 100644 --- a/hecl/include/HECL/Backend/GX.hpp +++ b/hecl/include/HECL/Backend/GX.hpp @@ -414,7 +414,15 @@ struct GX : IBackend color[0] = uint8_t(std::min(std::max(vec.vec[0] * 255.f, 0.f), 255.f)); color[1] = uint8_t(std::min(std::max(vec.vec[1] * 255.f, 0.f), 255.f)); color[2] = uint8_t(std::min(std::max(vec.vec[2] * 255.f, 0.f), 255.f)); - color[3] = 0; + color[3] = uint8_t(std::min(std::max(vec.vec[3] * 255.f, 0.f), 255.f)); + return *this; + } + Color& operator=(const atVec3f& vec) + { + color[0] = uint8_t(std::min(std::max(vec.vec[0] * 255.f, 0.f), 255.f)); + color[1] = uint8_t(std::min(std::max(vec.vec[1] * 255.f, 0.f), 255.f)); + color[2] = uint8_t(std::min(std::max(vec.vec[2] * 255.f, 0.f), 255.f)); + color[3] = 0xff; return *this; } Color& operator=(uint8_t val) @@ -426,6 +434,7 @@ struct GX : IBackend return *this; } Color(const atVec4f& vec) {*this = vec;} + Color(const atVec3f& vec) {*this = vec;} Color(uint8_t val) {*this = val;} bool operator==(const Color& other) const {return num == other.num;} bool operator!=(const Color& other) const {return num != other.num;} @@ -444,6 +453,68 @@ struct GX : IBackend int m_alphaTraceStage = -1; + bool operator==(const GX& other) const + { + if (m_tcgCount != other.m_tcgCount) + return false; + if (m_tevCount != other.m_tevCount) + return false; + if (m_blendSrc != other.m_blendSrc) + return false; + if (m_blendDst != other.m_blendDst) + return false; + if (m_kcolorCount != other.m_kcolorCount) + return false; + for (unsigned i=0 ; i= 4) diag.reportBackendErr(loc, "GX KColor overflow"); m_kcolors[m_kcolorCount] = color; + m_kcolors[m_kcolorCount].color[3] = 0; return m_kcolorCount++; }