Skip to content

Commit

Permalink
[BSP converter] De-duplicate materials during conversion.
Browse files Browse the repository at this point in the history
  • Loading branch information
num0005 committed Aug 14, 2021
1 parent db1c1fa commit da65d30
Show file tree
Hide file tree
Showing 7 changed files with 112 additions and 6 deletions.
6 changes: 6 additions & 0 deletions H2Codez/Common/BasicTagTypes.cpp
@@ -0,0 +1,6 @@
#include "BasicTagTypes.h"
#include "TagInterface.h"

int32_t tag_block_add_impl(tag_block_ref* block) {
return tags::add_block_element(block);
}
44 changes: 44 additions & 0 deletions H2Codez/Common/BasicTagTypes.h
Expand Up @@ -12,6 +12,23 @@ struct tag_reference
const char *tag_name;
int field_8;
datum tag_index;

bool operator==(const tag_reference& other) const {
if (tag_type != other.tag_type)
return false;
if (strcmp(tag_name, other.tag_name) == 0)
return true;

// maybe sometimes different names could result in the same tag getting loaded? not sure
if (tag_index == NONE)
return false; // ignore false positives from two unloadable tags

return tag_index == other.tag_index;
}

bool operator!=(const tag_reference& other) const {
return !operator==(other);
}
};
CHECK_STRUCT_SIZE(tag_reference, 16);

Expand All @@ -21,6 +38,9 @@ struct tag_block;

typedef tag_block<void> tag_block_ref;

// I hate this, but I don't feel like refactoring
int32_t tag_block_add_impl(tag_block_ref* block);

template <typename T = void>
struct tag_block
{
Expand All @@ -38,6 +58,14 @@ struct tag_block
return get_ref();
}

int32_t add() {
return tag_block_add_impl(get_ref());
}

int32_t add(const T *value) {
return add_impl(value);
}

bool is_valid() const
{
if (reinterpret_cast<size_t>(this->data) == NONE)
Expand Down Expand Up @@ -145,6 +173,22 @@ struct tag_block
uint8_t *data_char = reinterpret_cast<uint8_t*>(this->data);
return &data_char[element_size * idx];
}

template<typename T1>
int32_t add_impl(const T1* value) {
int32_t new_index = add();
if (new_index == NONE)
return NONE;

*get_element(new_index) = *(T*)value;

return new_index;
}

template<>
int32_t add_impl(const void* value) {
ASSERT_CHECK(false && "add(T *value) is not supported for tag_block_ref");
}
};
CHECK_STRUCT_SIZE(tag_block<void>, 12);
CHECK_STRUCT_SIZE(tag_block_ref, 12);
Expand Down
5 changes: 5 additions & 0 deletions H2Codez/Common/BlamBaseTypes.h
Expand Up @@ -124,6 +124,11 @@ struct blam_tag
return this->as_int() == other.as_int();
}

constexpr bool operator!=(const blam_tag& other) const
{
return !(operator==(other));
}

constexpr static blam_tag null()
{
return blam_tag(0xFFFFFFFF);
Expand Down
1 change: 1 addition & 0 deletions H2Codez/H2Codez.vcxproj
Expand Up @@ -230,6 +230,7 @@
<ItemGroup>
<ClCompile Include="COLLADA\COLLADA.cpp" />
<ClCompile Include="Common\AssemblyLayoutGenerator.cpp" />
<ClCompile Include="Common\BasicTagTypes.cpp" />
<ClCompile Include="Common\Cache.cpp" />
<ClCompile Include="Common\HaloScript.cpp" />
<ClCompile Include="Common\Pathfinding.cpp" />
Expand Down
3 changes: 3 additions & 0 deletions H2Codez/H2Codez.vcxproj.filters
Expand Up @@ -499,6 +499,9 @@
<ClCompile Include="H2Sapien\PlayerControl.cpp">
<Filter>Source Files\Patches\H2Sapien</Filter>
</ClCompile>
<ClCompile Include="Common\BasicTagTypes.cpp">
<Filter>Source Files\Common Interfaces\Tags</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="Resources\H2Sapien.rc">
Expand Down
33 changes: 27 additions & 6 deletions H2Codez/H2Tool/H2Tool_extra_commands.inl
Expand Up @@ -594,7 +594,31 @@ static bool _cdecl h2pc_generate_render_model(datum tag, file_reference& FILE_RE

if (ASSERT_CHECK(section->sectionData.size == 1) && LOG_CHECK(cluster->clusterData.size == 1))
{
// copy data from the cluster to the section
ASSERT_CHECK(render_model->materials.size <= 0x100);
ASSERT_CHECK(sbsp->materials.size <= 0x100);

// copy materials or map them to existing ones
// there are at most 0x100 materials per section (hopefully less)
short material_map[0x100] = {};

for (short i = 0; i < sbsp->materials.size; i++)
{
const global_geometry_material_block* bsp_material = sbsp->materials[i];

int32_t found = render_model->materials.find_element(
[bsp_material](const global_geometry_material_block* block) -> bool {
return *block == *bsp_material;
}
);

int32_t material_index = found == NONE ? render_model->materials.add(bsp_material) : found;

ASSERT_CHECK(material_index <= 0x100);
material_map[i] = static_cast<short>(material_index);
}


// copy the remaining data from the cluster to the section

auto *section_data = section->sectionData[0];
auto *cluster_data = cluster->clusterData[0];
Expand All @@ -606,12 +630,9 @@ static bool _cdecl h2pc_generate_render_model(datum tag, file_reference& FILE_RE
copy_block(stripIndices);
copy_block(vertexBuffers);
#undef copy_block
// fix materials index
// map material index to new one
for (auto& part : section_data->section.parts)
part.material += static_cast<short>(render_model->materials.size);

// copy over materials for this BSP
tags::copy_block(&sbsp->materials, &render_model->materials);
part.material = material_map[part.material];

// add node map entry
tags::resize_block(&section_data->nodeMap, 1);
Expand Down
26 changes: 26 additions & 0 deletions H2Codez/Tags/GlobalGeometry.h
Expand Up @@ -279,6 +279,14 @@ struct global_geometry_material_property_block
Type type;
short intValue;
float realValue;

bool operator==(const global_geometry_material_property_block& other) {
return memcmp(this, &other, sizeof(global_geometry_material_property_block)) == 0;
}

bool operator!=(const global_geometry_material_property_block& other) {
return !operator==(other);
}
};
CHECK_STRUCT_SIZE(global_geometry_material_property_block, 8);

Expand All @@ -294,6 +302,24 @@ struct global_geometry_material_block
byte padding81[4];
byte breakableSurfaceIndex;
byte padding82[3];

bool operator==(const global_geometry_material_block& other) const
{
if (oldShader != other.oldShader)
return false;
if (shader != other.shader)
return false;
if (breakableSurfaceIndex != other.breakableSurfaceIndex)
return false;

if (properties.size != other.properties.size)
return false;
for (int i = 0; i < properties.size; i++)
if (*properties[i] != *other.properties[i])
return false;

return true;
}
};
CHECK_STRUCT_SIZE(global_geometry_material_block, 52);

Expand Down

0 comments on commit da65d30

Please sign in to comment.