Skip to content

Commit

Permalink
Add hfrag, clean up some background renderer stuff (#3509)
Browse files Browse the repository at this point in the history
This adds hfrag, but with a few remaining issues:
- The textures aren't animated. Instead, it just uses one texture.
- The texture filtering isn't as good as at it could be.

I also cleaned up a few issues with the background renderers:
- Cleaned up some stuff that is common to hfrag, tie, tfrag, shrub
- Moved time-of-day color packing stuff to FR3 creation, rather than at
level load. This appears to reduce the frame time spikes when a level is
first drawn by about 5 or 6 ms in big levels.
- Cleaned up the x86 specific stuff used in time of day. Now there's
only one place where we have an `ifdef`, rather than spreading it all
over the rendering code.
  • Loading branch information
water111 authored May 10, 2024
1 parent 949508d commit 5b04be2
Show file tree
Hide file tree
Showing 80 changed files with 13,081 additions and 977 deletions.
58 changes: 50 additions & 8 deletions common/custom_data/TFrag3Data.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@

namespace tfrag3 {

void PackedTimeOfDay::serialize(Serializer& ser) {
ser.from_pod_vector(&data);
ser.from_ptr(&color_count);
}

void PackedTieVertices::serialize(Serializer& ser) {
ser.from_pod_vector(&color_indices);
ser.from_pod_vector(&matrices);
Expand Down Expand Up @@ -72,10 +77,9 @@ void TfragTree::serialize(Serializer& ser) {
draw.serialize(ser);
}

// ser.from_pod_vector(&vertices);
ser.from_pod_vector(&packed_vertices.vertices);
ser.from_pod_vector(&packed_vertices.cluster_origins);
ser.from_pod_vector(&colors);
colors.serialize(ser);
bvh.serialize(ser);
ser.from_ptr(&use_strips);
}
Expand Down Expand Up @@ -399,15 +403,15 @@ void TieTree::serialize(Serializer& ser) {
}

packed_vertices.serialize(ser);
ser.from_pod_vector(&colors);
colors.serialize(ser);
bvh.serialize(ser);

ser.from_ptr(&has_per_proto_visibility_toggle);
ser.from_string_vector(&proto_names);
}

void ShrubTree::serialize(Serializer& ser) {
ser.from_pod_vector(&time_of_day_colors);
time_of_day_colors.serialize(ser);
ser.from_pod_vector(&indices);
packed_vertices.serialize(ser);
if (ser.is_saving()) {
Expand All @@ -423,6 +427,30 @@ void ShrubTree::serialize(Serializer& ser) {
ser.from_string_vector(&proto_names);
}

void HfragmentBucket::serialize(Serializer& ser) {
ser.from_pod_vector(&corners);
ser.from_ptr(&montage_table);
}

void Hfragment::serialize(Serializer& ser) {
ser.from_pod_vector(&vertices);
ser.from_pod_vector(&indices);
ser.from_pod_vector(&corners);

if (ser.is_saving()) {
ser.save<size_t>(buckets.size());
} else {
buckets.resize(ser.load<size_t>());
}
for (auto& x : buckets) {
x.serialize(ser);
}
time_of_day_colors.serialize(ser);
ser.from_ptr(&wang_tree_tex_id);
ser.from_ptr(&draw_mode);
ser.from_ptr(&occlusion_offset);
}

void BVH::serialize(Serializer& ser) {
ser.from_ptr(&first_leaf_node);
ser.from_ptr(&last_leaf_node);
Expand Down Expand Up @@ -605,6 +633,8 @@ void Level::serialize(Serializer& ser) {
tree.serialize(ser);
}

hfrag.serialize(ser);

collision.serialize(ser);
merc_data.serialize(ser);

Expand Down Expand Up @@ -655,8 +685,7 @@ void PackedShrubVertices::memory_usage(MemoryUsageTracker* tracker) const {
}

void ShrubTree::memory_usage(MemoryUsageTracker* tracker) const {
tracker->add(MemoryUsageCategory::SHRUB_TIME_OF_DAY,
sizeof(TimeOfDayColor) * time_of_day_colors.size());
tracker->add(MemoryUsageCategory::SHRUB_TIME_OF_DAY, sizeof(u8) * time_of_day_colors.data.size());
packed_vertices.memory_usage(tracker);
tracker->add(MemoryUsageCategory::SHRUB_DRAW, sizeof(ShrubDraw) * static_draws.size());
tracker->add(MemoryUsageCategory::SHRUB_IND, sizeof(u32) * indices.size());
Expand Down Expand Up @@ -684,7 +713,7 @@ void TieTree::memory_usage(MemoryUsageTracker* tracker) const {
draw.vis_groups.size() * sizeof(StripDraw::VisGroup));
}
packed_vertices.memory_usage(tracker);
tracker->add(MemoryUsageCategory::TIE_TIME_OF_DAY, sizeof(TimeOfDayColor) * colors.size());
tracker->add(MemoryUsageCategory::TIE_TIME_OF_DAY, sizeof(u8) * colors.data.size());

for (auto& draw : instanced_wind_draws) {
draw.memory_usage(tracker);
Expand All @@ -708,7 +737,7 @@ void TfragTree::memory_usage(MemoryUsageTracker* tracker) const {
draw.vis_groups.size() * sizeof(StripDraw::VisGroup));
}
packed_vertices.memory_usage(tracker);
tracker->add(MemoryUsageCategory::TFRAG_TIME_OF_DAY, sizeof(TimeOfDayColor) * colors.size());
tracker->add(MemoryUsageCategory::TFRAG_TIME_OF_DAY, sizeof(u8) * colors.data.size());
tracker->add(MemoryUsageCategory::TFRAG_BVH, sizeof(VisNode) * bvh.vis_nodes.size());
}

Expand All @@ -721,6 +750,13 @@ void IndexTexture::memory_usage(MemoryUsageTracker* tracker) const {
tracker->add(MemoryUsageCategory::SPECIAL_TEXTURE, 256 * 4); // clut
}

void Hfragment::memory_usage(tfrag3::MemoryUsageTracker* tracker) const {
tracker->add(MemoryUsageCategory::HFRAG_VERTS, vertices.size() * sizeof(HfragmentVertex));
tracker->add(MemoryUsageCategory::HFRAG_INDEX, indices.size() * sizeof(u32));
tracker->add(MemoryUsageCategory::HFRAG_TIME_OF_DAY, time_of_day_colors.data.size() * sizeof(u8));
tracker->add(MemoryUsageCategory::HFRAG_CORNERS, corners.size() * sizeof(HfragmentCorner));
}

void Level::memory_usage(MemoryUsageTracker* tracker) const {
for (const auto& texture : textures) {
texture.memory_usage(tracker);
Expand All @@ -741,6 +777,7 @@ void Level::memory_usage(MemoryUsageTracker* tracker) const {
for (const auto& tree : shrub_trees) {
tree.memory_usage(tracker);
}
hfrag.memory_usage(tracker);
collision.memory_usage(tracker);
merc_data.memory_usage(tracker);
}
Expand Down Expand Up @@ -784,6 +821,11 @@ void print_memory_usage(const tfrag3::Level& lev, int uncompressed_data_size) {
{"merc-mod-draw-1", mem_use.data[tfrag3::MemoryUsageCategory::MERC_MOD_DRAW_1]},
{"merc-mod-draw-2", mem_use.data[tfrag3::MemoryUsageCategory::MERC_MOD_DRAW_2]},
{"blerc", mem_use.data[tfrag3::MemoryUsageCategory::BLERC]},
{"hfrag-verts", mem_use.data[tfrag3::MemoryUsageCategory::HFRAG_VERTS]},
{"hfrag-index", mem_use.data[tfrag3::MemoryUsageCategory::HFRAG_INDEX]},
{"hfrag-time-of-day", mem_use.data[tfrag3::MemoryUsageCategory::HFRAG_TIME_OF_DAY]},
{"hfrag-corners", mem_use.data[tfrag3::MemoryUsageCategory::HFRAG_CORNERS]}

};
for (auto& known : known_categories) {
total_accounted += known.second;
Expand Down
80 changes: 64 additions & 16 deletions common/custom_data/Tfrag3Data.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ namespace tfrag3 {
// - if changing any large things (vertices, vis, bvh, colors, textures) update get_memory_usage
// - if adding a new category to the memory usage, update extract_level to print it.

constexpr int TFRAG3_VERSION = 39;
constexpr int TFRAG3_VERSION = 40;

enum MemoryUsageCategory {
TEXTURE,
Expand Down Expand Up @@ -61,6 +61,11 @@ enum MemoryUsageCategory {
MERC_MOD_TABLE,
BLERC,

HFRAG_VERTS,
HFRAG_INDEX,
HFRAG_TIME_OF_DAY,
HFRAG_CORNERS,

COLLISION,

NUM_CATEGORIES
Expand Down Expand Up @@ -269,18 +274,23 @@ struct BVH {
void serialize(Serializer& ser);
};

// A time-of-day color. Each stores 8 colors. At a given "time of day", they are interpolated
// to find a single color which goes into a color palette.
struct TimeOfDayColor {
math::Vector<u8, 4> rgba[8];
// This is split into groups of 4 colors.
// The data in these groups is stored first by palette, then color, then channel.
struct PackedTimeOfDay {
std::vector<u8> data;
u32 color_count = 0;
void serialize(Serializer& ser);

bool operator==(const TimeOfDayColor& other) const {
for (size_t i = 0; i < 8; i++) {
if (rgba[i] != other.rgba[i]) {
return false;
}
}
return true;
u8 read(int color, int palette, int channel) const {
const int color_quad = color / 4;
const int color_in_quad = color % 4;
return data[color_quad * 4 * 4 * 8 + palette * 4 * 4 + color_in_quad * 4 + channel];
}

u8& read(int color, int palette, int channel) {
const int color_quad = color / 4;
const int color_in_quad = color % 4;
return data[color_quad * 4 * 4 * 8 + palette * 4 * 4 + color_in_quad * 4 + channel];
}
};

Expand Down Expand Up @@ -319,8 +329,8 @@ struct TfragTree {
TFragmentTreeKind kind; // our tfrag kind
std::vector<StripDraw> draws; // the actual topology and settings
PackedTfragVertices packed_vertices;
std::vector<TimeOfDayColor> colors; // vertex colors (pre-interpolation)
BVH bvh; // the bvh for frustum culling
PackedTimeOfDay colors; // vertex colors (pre-interpolation)
BVH bvh; // the bvh for frustum culling
bool use_strips = true;

struct {
Expand Down Expand Up @@ -401,7 +411,7 @@ struct TieTree {
std::array<u32, kNumTieCategories + 1> category_draw_indices;

PackedTieVertices packed_vertices;
std::vector<TimeOfDayColor> colors; // vertex colors (pre-interpolation)
PackedTimeOfDay colors; // vertex colors (pre-interpolation)

std::vector<InstancedStripDraw> instanced_wind_draws;
std::vector<TieWindInstance> wind_instance_info;
Expand All @@ -422,7 +432,7 @@ struct TieTree {

struct ShrubTree {
// todo some visibility structure
std::vector<TimeOfDayColor> time_of_day_colors; // multiplier colors
PackedTimeOfDay time_of_day_colors; // multiplier colors

PackedShrubVertices packed_vertices;
std::vector<ShrubDraw> static_draws; // the actual topology and settings
Expand All @@ -441,6 +451,43 @@ struct ShrubTree {
void unpack();
};

struct HfragmentVertex {
float height = 0;
u32 vi = 0;
u16 color_index = 0;
u8 u = 0, v = 0;
u32 pad = 0;
};

struct HfragmentCorner {
math::Vector<float, 4> bsphere;
u32 vis_id = 0;
u32 index_start = 0;
u32 index_length = 0;
u32 num_tris = 0;
};

struct HfragmentBucket {
std::vector<u32> corners;
std::array<u16, 16> montage_table;
void serialize(Serializer& ser);
};

struct Hfragment {
std::vector<HfragmentVertex> vertices;
std::vector<u32> indices;
std::vector<HfragmentCorner> corners;
std::vector<HfragmentBucket> buckets;
PackedTimeOfDay time_of_day_colors;

std::array<s32, 4> wang_tree_tex_id;
DrawMode draw_mode;
u32 occlusion_offset;

void serialize(Serializer& ser);
void memory_usage(MemoryUsageTracker* tracker) const;
};

struct CollisionMesh {
struct Vertex {
float x, y, z;
Expand Down Expand Up @@ -566,6 +613,7 @@ struct Level {
std::array<std::vector<TfragTree>, TFRAG_GEOS> tfrag_trees;
std::array<std::vector<TieTree>, TIE_GEOS> tie_trees;
std::vector<ShrubTree> shrub_trees;
Hfragment hfrag;
CollisionMesh collision;
MercModelGroup merc_data;
u16 version2 = TFRAG3_VERSION;
Expand Down
1 change: 1 addition & 0 deletions decompiler/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ add_library(
level_extractor/extract_actors.cpp
level_extractor/extract_collide_frags.cpp
level_extractor/extract_common.cpp
level_extractor/extract_hfrag.cpp
level_extractor/extract_joint_group.cpp
level_extractor/extract_level.cpp
level_extractor/extract_merc.cpp
Expand Down
Loading

0 comments on commit 5b04be2

Please sign in to comment.