mirror of
https://github.com/open-goal/jak-project.git
synced 2024-10-20 11:26:18 -04:00
Support extracting collision to obj for jak2/3 formats (#3292)
![image](https://github.com/open-goal/jak-project/assets/2515356/b4d43254-4fc4-4f66-92d1-0d61e471b90e) ![image](https://github.com/open-goal/jak-project/assets/2515356/d2fa9fb8-5f51-43c5-8e0e-b51b64499b72)
This commit is contained in:
parent
b0713641e7
commit
9d680a0aba
|
@ -1,5 +1,6 @@
|
||||||
#include "extract_collide_frags.h"
|
#include "extract_collide_frags.h"
|
||||||
|
|
||||||
|
#include "common/log/log.h"
|
||||||
#include "common/util/FileUtil.h"
|
#include "common/util/FileUtil.h"
|
||||||
|
|
||||||
namespace decompiler {
|
namespace decompiler {
|
||||||
|
@ -230,6 +231,7 @@ void set_vertices_for_tri(tfrag3::CollisionMesh::Vertex* out, const math::Vector
|
||||||
|
|
||||||
void extract_collide_frags(const level_tools::DrawableTreeCollideFragment* tree,
|
void extract_collide_frags(const level_tools::DrawableTreeCollideFragment* tree,
|
||||||
const std::vector<const level_tools::DrawableTreeInstanceTie*>& ties,
|
const std::vector<const level_tools::DrawableTreeInstanceTie*>& ties,
|
||||||
|
const Config& config,
|
||||||
const std::string& debug_name,
|
const std::string& debug_name,
|
||||||
tfrag3::Level& out,
|
tfrag3::Level& out,
|
||||||
bool dump_level) {
|
bool dump_level) {
|
||||||
|
@ -260,8 +262,8 @@ void extract_collide_frags(const level_tools::DrawableTreeCollideFragment* tree,
|
||||||
|
|
||||||
if (dump_level) {
|
if (dump_level) {
|
||||||
auto debug_out = debug_dump_to_obj(all_frags);
|
auto debug_out = debug_dump_to_obj(all_frags);
|
||||||
auto file_path =
|
auto file_path = file_util::get_file_path(
|
||||||
file_util::get_file_path({"debug_out", fmt::format("collide-{}.obj", debug_name)});
|
{fmt::format("debug_out/{}", config.game_name), fmt::format("collide-{}.obj", debug_name)});
|
||||||
file_util::create_dir_if_needed_for_file(file_path);
|
file_util::create_dir_if_needed_for_file(file_path);
|
||||||
file_util::write_text_file(file_path, debug_out);
|
file_util::write_text_file(file_path, debug_out);
|
||||||
}
|
}
|
||||||
|
@ -408,10 +410,40 @@ void handle_collide_fragment(const TypedRef& collide_fragment,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string debug_dump_to_obj(const std::vector<tfrag3::CollisionMesh::Vertex>& verts_in) {
|
||||||
|
std::vector<math::Vector4f> verts;
|
||||||
|
std::vector<math::Vector<u32, 3>> faces;
|
||||||
|
|
||||||
|
for (auto& v : verts_in) {
|
||||||
|
verts.emplace_back(v.x / 4096.0, v.y / 4096.0, v.z / 4096.0, 1.0);
|
||||||
|
|
||||||
|
u32 v_len = verts.size();
|
||||||
|
if (v_len % 3 == 0) {
|
||||||
|
// add face from last 3 vertices
|
||||||
|
faces.emplace_back(v_len - 2, v_len - 1, v_len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string result;
|
||||||
|
for (auto& vert : verts) {
|
||||||
|
result += fmt::format("v {} {} {}\n", vert.x(), vert.y(), vert.z());
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& face : faces) {
|
||||||
|
result += fmt::format("f {}/{} {}/{} {}/{}\n", face.x(), face.x(), face.y(), face.y(), face.z(),
|
||||||
|
face.z());
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
void extract_collide_frags(const level_tools::CollideHash& chash,
|
void extract_collide_frags(const level_tools::CollideHash& chash,
|
||||||
const std::vector<const level_tools::DrawableTreeInstanceTie*>& ties,
|
const std::vector<const level_tools::DrawableTreeInstanceTie*>& ties,
|
||||||
|
const Config& config,
|
||||||
|
const std::string& debug_name,
|
||||||
const decompiler::DecompilerTypeSystem& dts,
|
const decompiler::DecompilerTypeSystem& dts,
|
||||||
tfrag3::Level& out) {
|
tfrag3::Level& out,
|
||||||
|
bool dump_level) {
|
||||||
// We need to find all collide-hash-fragments, but we can't just scan through the entire file.
|
// We need to find all collide-hash-fragments, but we can't just scan through the entire file.
|
||||||
// for collide-hash-fragments, we need to figure out which TIEs they belong to, to apply the
|
// for collide-hash-fragments, we need to figure out which TIEs they belong to, to apply the
|
||||||
// instance transformation matrix.
|
// instance transformation matrix.
|
||||||
|
@ -474,5 +506,15 @@ void extract_collide_frags(const level_tools::CollideHash& chash,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (dump_level) {
|
||||||
|
// out.collision.vertices every 3 vertices make a face, so it duplicates vertices in many cases
|
||||||
|
// for now debug_dump_to_obj isn't smart and doesn't hash these to save space or anything
|
||||||
|
auto debug_out = debug_dump_to_obj(out.collision.vertices);
|
||||||
|
auto file_path = file_util::get_file_path(
|
||||||
|
{fmt::format("debug_out/{}", config.game_name), fmt::format("collide-{}.obj", debug_name)});
|
||||||
|
file_util::create_dir_if_needed_for_file(file_path);
|
||||||
|
file_util::write_text_file(file_path, debug_out);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} // namespace decompiler
|
} // namespace decompiler
|
||||||
|
|
|
@ -8,13 +8,17 @@ namespace decompiler {
|
||||||
|
|
||||||
void extract_collide_frags(const level_tools::DrawableTreeCollideFragment* tree,
|
void extract_collide_frags(const level_tools::DrawableTreeCollideFragment* tree,
|
||||||
const std::vector<const level_tools::DrawableTreeInstanceTie*>& ties,
|
const std::vector<const level_tools::DrawableTreeInstanceTie*>& ties,
|
||||||
|
const Config& config,
|
||||||
const std::string& debug_name,
|
const std::string& debug_name,
|
||||||
tfrag3::Level& out,
|
tfrag3::Level& out,
|
||||||
bool dump_level);
|
bool dump_level);
|
||||||
|
|
||||||
void extract_collide_frags(const level_tools::CollideHash& chash,
|
void extract_collide_frags(const level_tools::CollideHash& chash,
|
||||||
const std::vector<const level_tools::DrawableTreeInstanceTie*>& ties,
|
const std::vector<const level_tools::DrawableTreeInstanceTie*>& ties,
|
||||||
|
const Config& config,
|
||||||
|
const std::string& debug_name,
|
||||||
const decompiler::DecompilerTypeSystem& dts,
|
const decompiler::DecompilerTypeSystem& dts,
|
||||||
tfrag3::Level& out);
|
tfrag3::Level& out,
|
||||||
|
bool dump_level);
|
||||||
|
|
||||||
} // namespace decompiler
|
} // namespace decompiler
|
||||||
|
|
|
@ -159,9 +159,10 @@ std::vector<level_tools::TextureRemap> extract_tex_remap(const ObjectFileDB& db,
|
||||||
level_tools::BspHeader extract_bsp_from_level(const ObjectFileDB& db,
|
level_tools::BspHeader extract_bsp_from_level(const ObjectFileDB& db,
|
||||||
const TextureDB& tex_db,
|
const TextureDB& tex_db,
|
||||||
const std::string& dgo_name,
|
const std::string& dgo_name,
|
||||||
const DecompileHacks& hacks,
|
const Config& config,
|
||||||
bool extract_collision,
|
bool extract_collision,
|
||||||
tfrag3::Level& level_data) {
|
tfrag3::Level& level_data) {
|
||||||
|
auto hacks = config.hacks;
|
||||||
auto bsp_rec = get_bsp_file(db.obj_files_by_dgo.at(dgo_name), dgo_name);
|
auto bsp_rec = get_bsp_file(db.obj_files_by_dgo.at(dgo_name), dgo_name);
|
||||||
if (!bsp_rec) {
|
if (!bsp_rec) {
|
||||||
lg::warn("Skipping extract for {} because the BSP file was not found", dgo_name);
|
lg::warn("Skipping extract for {} because the BSP file was not found", dgo_name);
|
||||||
|
@ -236,8 +237,8 @@ level_tools::BspHeader extract_bsp_from_level(const ObjectFileDB& db,
|
||||||
ASSERT(as_collide_frags);
|
ASSERT(as_collide_frags);
|
||||||
ASSERT(!got_collide);
|
ASSERT(!got_collide);
|
||||||
got_collide = true;
|
got_collide = true;
|
||||||
extract_collide_frags(as_collide_frags, all_ties, fmt::format("{}-{}-collide", dgo_name, i++),
|
extract_collide_frags(as_collide_frags, all_ties, config,
|
||||||
level_data, false);
|
fmt::format("{}-{}-collide", dgo_name, i++), level_data, false);
|
||||||
} else {
|
} else {
|
||||||
lg::print(" unsupported tree {}\n", draw_tree->my_type());
|
lg::print(" unsupported tree {}\n", draw_tree->my_type());
|
||||||
}
|
}
|
||||||
|
@ -245,7 +246,8 @@ level_tools::BspHeader extract_bsp_from_level(const ObjectFileDB& db,
|
||||||
|
|
||||||
if (bsp_header.collide_hash.num_items) {
|
if (bsp_header.collide_hash.num_items) {
|
||||||
ASSERT(!got_collide);
|
ASSERT(!got_collide);
|
||||||
extract_collide_frags(bsp_header.collide_hash, all_ties, db.dts, level_data);
|
extract_collide_frags(bsp_header.collide_hash, all_ties, config,
|
||||||
|
fmt::format("{}-{}-collide", dgo_name, i++), db.dts, level_data, false);
|
||||||
}
|
}
|
||||||
level_data.level_name = level_name;
|
level_data.level_name = level_name;
|
||||||
|
|
||||||
|
@ -348,7 +350,7 @@ void extract_from_level(const ObjectFileDB& db,
|
||||||
|
|
||||||
// the bsp header file data
|
// the bsp header file data
|
||||||
auto bsp_header =
|
auto bsp_header =
|
||||||
extract_bsp_from_level(db, tex_db, dgo_name, config.hacks, extract_collision, level_data);
|
extract_bsp_from_level(db, tex_db, dgo_name, config, extract_collision, level_data);
|
||||||
extract_art_groups_from_level(db, tex_db, bsp_header.texture_remap_table, dgo_name, level_data,
|
extract_art_groups_from_level(db, tex_db, bsp_header.texture_remap_table, dgo_name, level_data,
|
||||||
art_group_data);
|
art_group_data);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue