Optimization refinements in mesh cooker

This commit is contained in:
Jack Andersen 2015-10-18 17:27:58 -10:00
parent 2044a4b9b1
commit 3a4647e4c3
6 changed files with 155 additions and 8 deletions

View File

@ -654,6 +654,7 @@ uint32_t BlenderConnection::DataStream::Mesh::SkinBanks::addSurface
if (banks.empty())
addSkinBank(skinSlotCount);
std::vector<uint32_t> toAdd;
if (skinSlotCount > 0)
toAdd.reserve(skinSlotCount);
std::vector<std::vector<uint32_t>>::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;

View File

@ -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,6 +373,7 @@ public:
std::vector<std::vector<uint32_t>>::iterator addSkinBank(int skinSlotCount)
{
banks.emplace_back();
if (skinSlotCount > 0)
banks.back().reserve(skinSlotCount);
return banks.end() - 1;
}

View File

@ -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,7 +168,8 @@ 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:
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)
@ -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))

View File

@ -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()

View File

@ -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<m_tcgCount ; ++i)
{
const TexCoordGen& a = m_tcgs[i];
const TexCoordGen& b = other.m_tcgs[i];
if (a.m_src != b.m_src)
return false;
if (a.m_mtx != b.m_mtx)
return false;
}
for (unsigned i=0 ; i<m_tevCount ; ++i)
{
const TEVStage& a = m_tevs[i];
const TEVStage& b = other.m_tevs[i];
for (unsigned j=0 ; j<4 ; ++j)
if (a.m_color[j] != b.m_color[j])
return false;
for (unsigned j=0 ; j<4 ; ++j)
if (a.m_alpha[j] != b.m_alpha[j])
return false;
if (a.m_cop != b.m_cop)
return false;
if (a.m_aop != b.m_aop)
return false;
if (a.m_kColor != b.m_kColor)
return false;
if (a.m_kAlpha != b.m_kAlpha)
return false;
if (a.m_cRegOut != b.m_cRegOut)
return false;
if (a.m_aRegOut != b.m_aRegOut)
return false;
if (a.m_texMapIdx != b.m_texMapIdx)
return false;
if (a.m_texGenIdx != b.m_texGenIdx)
return false;
}
for (unsigned i=0 ; i<m_kcolorCount ; ++i)
{
const Color& a = m_kcolors[i];
const Color& b = other.m_kcolors[i];
if (a.num != b.num)
return false;
}
return true;
}
bool operator!=(const GX& other) const
{
return !(*this == other);
}
void reset(const IR& ir, Diagnostics& diag);
private:

View File

@ -14,6 +14,7 @@ unsigned GX::addKColor(Diagnostics& diag, const SourceLocation& loc, const Color
if (m_kcolorCount >= 4)
diag.reportBackendErr(loc, "GX KColor overflow");
m_kcolors[m_kcolorCount] = color;
m_kcolors[m_kcolorCount].color[3] = 0;
return m_kcolorCount++;
}