Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add MSAA 4x + lod picking for TIE & tfrag #1167

Merged
merged 8 commits into from
Feb 15, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 20 additions & 16 deletions common/custom_data/TFrag3Data.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,22 +111,26 @@ void Level::serialize(Serializer& ser) {
tex.serialize(ser);
}

if (ser.is_saving()) {
ser.save<size_t>(tfrag_trees.size());
} else {
tfrag_trees.resize(ser.load<size_t>());
}
for (auto& tree : tfrag_trees) {
tree.serialize(ser);
}

if (ser.is_saving()) {
ser.save<size_t>(tie_trees.size());
} else {
tie_trees.resize(ser.load<size_t>());
}
for (auto& tree : tie_trees) {
tree.serialize(ser);
for (int geom = 0; geom < 3; ++geom) {
if (ser.is_saving()) {
ser.save<size_t>(tfrag_trees[geom].size());
} else {
tfrag_trees[geom].resize(ser.load<size_t>());
}
for (auto& tree : tfrag_trees[geom]) {
tree.serialize(ser);
}
}

for (int geom = 0; geom < 4; ++geom) {
if (ser.is_saving()) {
ser.save<size_t>(tie_trees[geom].size());
} else {
tie_trees[geom].resize(ser.load<size_t>());
}
for (auto& tree : tie_trees[geom]) {
tree.serialize(ser);
}
}

ser.from_ptr(&version2);
Expand Down
6 changes: 3 additions & 3 deletions common/custom_data/Tfrag3Data.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

namespace tfrag3 {

constexpr int TFRAG3_VERSION = 9;
constexpr int TFRAG3_VERSION = 10;

// These vertices should be uploaded to the GPU at load time and don't change
struct PreloadedVertex {
Expand Down Expand Up @@ -161,8 +161,8 @@ struct Level {
u16 version = TFRAG3_VERSION;
std::string level_name;
std::vector<Texture> textures;
std::vector<TfragTree> tfrag_trees;
std::vector<TieTree> tie_trees;
std::array<std::vector<TfragTree>, 3> tfrag_trees;
std::array<std::vector<TieTree>, 4> tie_trees;
u16 version2 = TFRAG3_VERSION;
void serialize(Serializer& ser);
};
Expand Down
5 changes: 1 addition & 4 deletions common/util/FileUtil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,11 +100,8 @@ void write_binary_file(const std::string& name, const void* data, size_t size) {
fclose(fp);
}

void write_rgba_png(const std::string& name, void* data, int w, int h, bool compress) {
void write_rgba_png(const std::string& name, void* data, int w, int h) {
auto flags = 0;
if (!compress) {
flags = fpng::FPNG_FORCE_UNCOMPRESSED;
}

auto ok = fpng::fpng_encode_image_to_file(name.c_str(), data, w, h, 4, flags);

Expand Down
2 changes: 1 addition & 1 deletion common/util/FileUtil.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ std::string get_project_path();
std::string get_file_path(const std::vector<std::string>& input);
bool create_dir_if_needed(const std::string& path);
void write_binary_file(const std::string& name, const void* data, size_t size);
void write_rgba_png(const std::string& name, void* data, int w, int h, bool compress);
void write_rgba_png(const std::string& name, void* data, int w, int h);
void write_text_file(const std::string& file_name, const std::string& text);
std::vector<uint8_t> read_binary_file(const std::string& filename);
std::string read_text_file(const std::string& path);
Expand Down
2 changes: 1 addition & 1 deletion decompiler/config/all-types.gc
Original file line number Diff line number Diff line change
Expand Up @@ -19918,7 +19918,7 @@
(define-extern clone-anim-once (function handle int symbol string none :behavior process-drawable))
(define-extern convert-to-hud-object (function process-drawable hud none :behavior hud))
(define-extern clone-anim (function handle int symbol string none :behavior process-drawable))
(define-extern merc-eye-anim (function manipy none))
(define-extern merc-eye-anim (function process-drawable none))
(define-extern ja-anim-done? (function process symbol))
(define-extern command-get-camera (function object state state))
(define-extern camera-anim (function symbol basic entity (pointer process) :behavior camera-tracker)) ;; unused
Expand Down
10 changes: 5 additions & 5 deletions decompiler/data/tpage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -521,7 +521,7 @@ TPageResultStats process_tpage(ObjectFileData& data, TextureDB& texture_db) {
fmt::format(file_util::get_file_path(
{"assets", "textures", texture_page.name, "{}-{}-{}-{}.png"}),
data.name_in_dgo, tex.name, tex.w, tex.h),
out.data(), tex.w, tex.h, false);
out.data(), tex.w, tex.h);
texture_db.add_texture(texture_page.id, tex_id, out, tex.w, tex.h, tex.name,
texture_page.name);
stats.successful_textures++;
Expand Down Expand Up @@ -569,7 +569,7 @@ TPageResultStats process_tpage(ObjectFileData& data, TextureDB& texture_db) {
fmt::format(file_util::get_file_path(
{"assets", "textures", texture_page.name, "{}-{}-{}-{}.png"}),
data.name_in_dgo, tex.name, tex.w, tex.h),
out.data(), tex.w, tex.h, false);
out.data(), tex.w, tex.h);
texture_db.add_texture(texture_page.id, tex_id, out, tex.w, tex.h, tex.name,
texture_page.name);
stats.successful_textures++;
Expand Down Expand Up @@ -599,7 +599,7 @@ TPageResultStats process_tpage(ObjectFileData& data, TextureDB& texture_db) {
fmt::format(file_util::get_file_path(
{"assets", "textures", texture_page.name, "{}-{}-{}-{}.png"}),
data.name_in_dgo, tex.name, tex.w, tex.h),
out.data(), tex.w, tex.h, false);
out.data(), tex.w, tex.h);
texture_db.add_texture(texture_page.id, tex_id, out, tex.w, tex.h, tex.name,
texture_page.name);
stats.successful_textures++;
Expand Down Expand Up @@ -645,7 +645,7 @@ TPageResultStats process_tpage(ObjectFileData& data, TextureDB& texture_db) {
fmt::format(file_util::get_file_path(
{"assets", "textures", texture_page.name, "{}-{}-{}-{}.png"}),
data.name_in_dgo, tex.name, tex.w, tex.h),
out.data(), tex.w, tex.h, false);
out.data(), tex.w, tex.h);
texture_db.add_texture(texture_page.id, tex_id, out, tex.w, tex.h, tex.name,
texture_page.name);
stats.successful_textures++;
Expand Down Expand Up @@ -691,7 +691,7 @@ TPageResultStats process_tpage(ObjectFileData& data, TextureDB& texture_db) {
fmt::format(file_util::get_file_path(
{"assets", "textures", texture_page.name, "{}-{}-{}-{}.png"}),
data.name_in_dgo, tex.name, tex.w, tex.h),
out.data(), tex.w, tex.h, false);
out.data(), tex.w, tex.h);
texture_db.add_texture(texture_page.id, tex_id, out, tex.w, tex.h, tex.name,
texture_page.name);
stats.successful_textures++;
Expand Down
140 changes: 74 additions & 66 deletions decompiler/level_extractor/extract_tfrag.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@

namespace decompiler {
namespace {

static constexpr int GEOM_MAX = 3;

/*!
* Get the index of the first draw node in an array. Works for node or tfrag.
*/
Expand Down Expand Up @@ -536,7 +539,8 @@ struct TFragColorUnpack {
}
};

void emulate_dma_building_for_tfrag(const level_tools::TFragment& frag,
void emulate_dma_building_for_tfrag(int geom,
const level_tools::TFragment& frag,
std::vector<u8>& vu_mem,
TFragColorUnpack& color_indices,
TFragExtractStats* stats) {
Expand All @@ -546,13 +550,13 @@ void emulate_dma_building_for_tfrag(const level_tools::TFragment& frag,
state.cl = 4;

// do the "canned" unpacks
if (frag.num_level0_colors == 0) {
if (frag.num_level0_colors == 0 || geom == 2) {
// we're using base
ASSERT(frag.num_level1_colors == 0);
// ASSERT(frag.num_level1_colors == 0);
stats->num_base++;
emulate_chain(state, frag.dma_qwc[1] * 4, (const u32*)frag.dma_base.data(), vu_mem.data());

} else if (frag.num_level1_colors == 0) {
} else if (frag.num_level1_colors == 0 || geom == 1) {
stats->num_l0++;
emulate_chain(state, frag.dma_qwc[3] * 4, (const u32*)frag.dma_common_and_level0.data(),
vu_mem.data());
Expand Down Expand Up @@ -2070,7 +2074,8 @@ void make_tfrag3_data(std::map<u32, std::vector<GroupedDraw>>& draws,
}
}

void emulate_tfrags(const std::vector<level_tools::TFragment>& frags,
void emulate_tfrags(int geom,
const std::vector<level_tools::TFragment>& frags,
const std::string& debug_name,
const std::vector<level_tools::TextureRemap>& map,
tfrag3::Level& level_out,
Expand All @@ -2087,7 +2092,7 @@ void emulate_tfrags(const std::vector<level_tools::TFragment>& frags,

for (auto& frag : frags) {
TFragColorUnpack color_indices;
emulate_dma_building_for_tfrag(frag, vu_mem, color_indices, &stats);
emulate_dma_building_for_tfrag(geom, frag, vu_mem, color_indices, &stats);
VuMemWrapper mem(vu_mem);
auto draws = emulate_tfrag_execution<false>(frag, mem, color_indices, &stats);
all_draws.insert(all_draws.end(), draws.begin(), draws.end());
Expand Down Expand Up @@ -2137,75 +2142,78 @@ void extract_tfrag(const level_tools::DrawableTreeTfrag* tree,
const std::vector<std::pair<int, int>>& expected_missing_textures,
tfrag3::Level& out,
bool dump_level) {
tfrag3::TfragTree this_tree;
if (tree->my_type() == "drawable-tree-tfrag") {
this_tree.kind = tfrag3::TFragmentTreeKind::NORMAL;
} else if (tree->my_type() == "drawable-tree-dirt-tfrag") {
this_tree.kind = tfrag3::TFragmentTreeKind::DIRT;
} else if (tree->my_type() == "drawable-tree-ice-tfrag") {
this_tree.kind = tfrag3::TFragmentTreeKind::ICE;
} else if (tree->my_type() == "drawable-tree-lowres-tfrag") {
this_tree.kind = tfrag3::TFragmentTreeKind::LOWRES;
} else if (tree->my_type() == "drawable-tree-trans-tfrag") {
this_tree.kind = tfrag3::TFragmentTreeKind::TRANS;
} else {
fmt::print("unknown tfrag tree kind: {}\n", tree->my_type());
ASSERT(false);
}
// go through 4 lods(?)
for (int geom = 0; geom < GEOM_MAX; ++geom) {
tfrag3::TfragTree this_tree;
if (tree->my_type() == "drawable-tree-tfrag") {
this_tree.kind = tfrag3::TFragmentTreeKind::NORMAL;
} else if (tree->my_type() == "drawable-tree-dirt-tfrag") {
this_tree.kind = tfrag3::TFragmentTreeKind::DIRT;
} else if (tree->my_type() == "drawable-tree-ice-tfrag") {
this_tree.kind = tfrag3::TFragmentTreeKind::ICE;
} else if (tree->my_type() == "drawable-tree-lowres-tfrag") {
this_tree.kind = tfrag3::TFragmentTreeKind::LOWRES;
} else if (tree->my_type() == "drawable-tree-trans-tfrag") {
this_tree.kind = tfrag3::TFragmentTreeKind::TRANS;
} else {
fmt::print("unknown tfrag tree kind: {}\n", tree->my_type());
ASSERT(false);
}

ASSERT(tree->length == (int)tree->arrays.size());
ASSERT(tree->length > 0);
ASSERT(tree->length == (int)tree->arrays.size());
ASSERT(tree->length > 0);

auto last_array = tree->arrays.back().get();
auto last_array = tree->arrays.back().get();

auto as_tfrag_array = dynamic_cast<level_tools::DrawableInlineArrayTFrag*>(last_array);
ASSERT(as_tfrag_array);
ASSERT(as_tfrag_array->length == (int)as_tfrag_array->tfragments.size());
ASSERT(as_tfrag_array->length > 0);
u16 idx = as_tfrag_array->tfragments.front().id;
for (auto& elt : as_tfrag_array->tfragments) {
ASSERT(elt.id == idx);
idx++;
}
bool ok = verify_node_indices(tree);
ASSERT(ok);
fmt::print(" tree has {} arrays and {} tfragments\n", tree->length, as_tfrag_array->length);

auto vis_nodes = extract_vis_data(tree, as_tfrag_array->tfragments.front().id);
this_tree.bvh.first_leaf_node = vis_nodes.first_child_node;
this_tree.bvh.last_leaf_node = vis_nodes.last_child_node;
this_tree.bvh.num_roots = vis_nodes.num_roots;
this_tree.bvh.only_children = vis_nodes.only_children;
this_tree.bvh.first_root = vis_nodes.first_root;
this_tree.bvh.vis_nodes = std::move(vis_nodes.vis_nodes);

std::unordered_map<int, int> tfrag_parents;
// for (auto& node : this_tree.vis_nodes) {
for (size_t node_idx = 0; node_idx < this_tree.bvh.vis_nodes.size(); node_idx++) {
const auto& node = this_tree.bvh.vis_nodes[node_idx];
if (node.flags == 0) {
for (int i = 0; i < node.num_kids; i++) {
tfrag_parents[node.child_id + i] = node_idx;
auto as_tfrag_array = dynamic_cast<level_tools::DrawableInlineArrayTFrag*>(last_array);
ASSERT(as_tfrag_array);
ASSERT(as_tfrag_array->length == (int)as_tfrag_array->tfragments.size());
ASSERT(as_tfrag_array->length > 0);
u16 idx = as_tfrag_array->tfragments.front().id;
for (auto& elt : as_tfrag_array->tfragments) {
ASSERT(elt.id == idx);
idx++;
}
bool ok = verify_node_indices(tree);
ASSERT(ok);
fmt::print(" tree has {} arrays and {} tfragments\n", tree->length, as_tfrag_array->length);

auto vis_nodes = extract_vis_data(tree, as_tfrag_array->tfragments.front().id);
this_tree.bvh.first_leaf_node = vis_nodes.first_child_node;
this_tree.bvh.last_leaf_node = vis_nodes.last_child_node;
this_tree.bvh.num_roots = vis_nodes.num_roots;
this_tree.bvh.only_children = vis_nodes.only_children;
this_tree.bvh.first_root = vis_nodes.first_root;
this_tree.bvh.vis_nodes = std::move(vis_nodes.vis_nodes);

std::unordered_map<int, int> tfrag_parents;
// for (auto& node : this_tree.vis_nodes) {
for (size_t node_idx = 0; node_idx < this_tree.bvh.vis_nodes.size(); node_idx++) {
const auto& node = this_tree.bvh.vis_nodes[node_idx];
if (node.flags == 0) {
for (int i = 0; i < node.num_kids; i++) {
tfrag_parents[node.child_id + i] = node_idx;
}
}
}
}
// ASSERT(result.vis_nodes.last_child_node + 1 == idx);
// ASSERT(result.vis_nodes.last_child_node + 1 == idx);

emulate_tfrags(as_tfrag_array->tfragments, debug_name, map, out, this_tree, tex_db,
expected_missing_textures, dump_level);
extract_time_of_day(tree, this_tree);
emulate_tfrags(geom, as_tfrag_array->tfragments, debug_name, map, out, this_tree, tex_db,
expected_missing_textures, dump_level);
extract_time_of_day(tree, this_tree);

for (auto& draw : this_tree.draws) {
for (auto& str : draw.vis_groups) {
auto it = tfrag_parents.find(str.vis_idx_in_pc_bvh);
if (it == tfrag_parents.end()) {
str.vis_idx_in_pc_bvh = UINT32_MAX;
} else {
str.vis_idx_in_pc_bvh = it->second;
for (auto& draw : this_tree.draws) {
for (auto& str : draw.vis_groups) {
auto it = tfrag_parents.find(str.vis_idx_in_pc_bvh);
if (it == tfrag_parents.end()) {
str.vis_idx_in_pc_bvh = UINT32_MAX;
} else {
str.vis_idx_in_pc_bvh = it->second;
}
}
merge_groups(draw.vis_groups);
}
merge_groups(draw.vis_groups);
out.tfrag_trees[geom].push_back(this_tree);
}
out.tfrag_trees.push_back(this_tree);
}
} // namespace decompiler
Loading