Skip to content

Commit

Permalink
custom level etie support for jak2/3, build actor changes
Browse files Browse the repository at this point in the history
  • Loading branch information
Hat-Kid committed Jan 26, 2025
1 parent 7348e6a commit bb262f1
Show file tree
Hide file tree
Showing 20 changed files with 184 additions and 78 deletions.
5 changes: 3 additions & 2 deletions common/util/gltf_util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -685,14 +685,15 @@ bool material_has_envmap(const tinygltf::Material& mat) {
}

bool envmap_is_valid(const tinygltf::Material& mat) {
if (material_has_envmap(mat) && mat.pbrMetallicRoughness.metallicRoughnessTexture.index < 0) {
auto envmap = material_has_envmap(mat);
if (envmap && mat.pbrMetallicRoughness.metallicRoughnessTexture.index < 0) {
lg::warn(fmt::format(
"Material \"{}\" has specular property set, but is missing a metallic roughness texture, "
"ignoring envmap!",
mat.name));
return false;
}
return true;
return envmap;
}

std::optional<int> find_single_skin(const tinygltf::Model& model,
Expand Down
8 changes: 4 additions & 4 deletions goal_src/jak1/game.gp
Original file line number Diff line number Diff line change
Expand Up @@ -218,15 +218,15 @@
)
)

(defmacro build-custom-level (name)
(defmacro build-custom-level (name &key (force-run #f) &key (gen-fr3 #t))
(let* ((path (string-append "custom_assets/jak1/levels/" name "/" name ".jsonc")))
`(defstep :in ,path
`(defstep :in '(,path ,(symbol->string force-run) ,(symbol->string gen-fr3))
:tool 'build-level
:out '(,(string-append "$OUT/obj/" name ".go")))))

(defmacro build-actor (name &key (gen-mesh #f))
(defmacro build-actor (name &key (gen-mesh #f) &key (force-run #f) &key (texture-bucket 0))
(let* ((path (string-append "custom_assets/jak1/models/custom_levels/" name ".glb")))
`(defstep :in '(,path ,(symbol->string gen-mesh))
`(defstep :in '(,path ,(symbol->string gen-mesh) ,(symbol->string force-run) ,(if (integer? texture-bucket) (int->string texture-bucket) (symbol->string texture-bucket)))
:tool 'build-actor
:out '(,(string-append "$OUT/obj/" name "-ag.go")))))

Expand Down
4 changes: 2 additions & 2 deletions goal_src/jak2/lib/project-lib.gp
Original file line number Diff line number Diff line change
Expand Up @@ -135,9 +135,9 @@
)
)

(defmacro build-custom-level (name)
(defmacro build-custom-level (name &key (force-run #f) &key (gen-fr3 #t))
(let* ((path (string-append "custom_assets/jak2/levels/" name "/" name ".jsonc")))
`(defstep :in ,path
`(defstep :in '(,path ,(symbol->string force-run) ,(symbol->string gen-fr3))
:tool 'build-level2
:out '(,(string-append "$OUT/obj/" name ".go")))))

Expand Down
4 changes: 2 additions & 2 deletions goal_src/jak3/lib/project-lib.gp
Original file line number Diff line number Diff line change
Expand Up @@ -247,8 +247,8 @@
)
)

(defmacro build-custom-level (name)
(defmacro build-custom-level (name &key (force-run #f) &key (gen-fr3 #t))
(let* ((path (string-append "custom_assets/jak3/levels/" name "/" name ".jsonc")))
`(defstep :in ,path
`(defstep :in '(,path ,(symbol->string force-run) ,(symbol->string gen-fr3))
:tool 'build-level3
:out '(,(string-append "$OUT/obj/" name ".go")))))
35 changes: 22 additions & 13 deletions goalc/build_actor/jak1/build_actor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -281,16 +281,25 @@ void ArtJointGeo::add_res() {
lump.add_res(
std::make_unique<ResRef>("collide-mesh-group", "array", mesh_slot, DEFAULT_RES_TIME));
}
// jgeo.lump.add_res(
// std::make_unique<ResInt32>("texture-level", std::vector<s32>{2}, DEFAULT_RES_TIME));
// jgeo.lump.add_res(std::make_unique<ResVector>(
// "trans-offset", std::vector<math::Vector4f>{{0.0f, 2048.0f, 0.0f, 1.0f}},
// DEFAULT_RES_TIME));
// jgeo.lump.add_res(
// std::make_unique<ResInt32>("joint-channel", std::vector<s32>{0}, DEFAULT_RES_TIME));
// jgeo.lump.add_res(std::make_unique<ResFloat>(
// "lod-dist", std::vector<float>{5000.0f * METER_LENGTH, 6000.0f * METER_LENGTH},
// DEFAULT_RES_TIME));
if (texture_bucket != -1) {
lump.add_res(std::make_unique<ResUint8>(
"texture-bucket", std::vector<u8>{static_cast<u8>(texture_bucket)}, DEFAULT_RES_TIME));
}
if (texture_level != -1) {
lump.add_res(std::make_unique<ResInt32>("texture-level", std::vector<s32>{texture_level},
DEFAULT_RES_TIME));
}
if (trans_offset != math::Vector4f{0.f, 0.f, 0.f, 1.f}) {
lump.add_res(std::make_unique<ResVector>(
"trans-offset", std::vector<math::Vector4f>{trans_offset}, DEFAULT_RES_TIME));
}
if (joint_channel != -1) {
lump.add_res(std::make_unique<ResInt32>("joint-channel", std::vector<s32>{joint_channel},
DEFAULT_RES_TIME));
}
if (!lod_dist.empty()) {
lump.add_res(std::make_unique<ResFloat>("lod-dist", lod_dist, DEFAULT_RES_TIME));
}
lump.sort_res();
}

Expand Down Expand Up @@ -721,7 +730,7 @@ std::vector<anim::CompressedAnim> process_anim(const tinygltf::Model& model,
*/
bool run_build_actor(const std::string& mdl_name,
const std::string& ag_out,
bool gen_collide_mesh) {
const BuildActorParams& params) {
std::string ag_name;
if (fs::exists(file_util::get_jak_project_dir() / mdl_name)) {
ag_name = fs::path(mdl_name).stem().string();
Expand Down Expand Up @@ -766,11 +775,11 @@ bool run_build_actor(const std::string& mdl_name,
}

std::vector<CollideMesh> mesh;
if (gen_collide_mesh) {
if (params.gen_collide_mesh) {
mesh = gen_collide_mesh_from_model(model, all_nodes, 3);
}

std::shared_ptr<ArtJointGeo> jgeo = std::make_shared<ArtJointGeo>(ag.name, mesh, joints);
std::shared_ptr<ArtJointGeo> jgeo = std::make_shared<ArtJointGeo>(ag.name, mesh, joints, params);

ag.elts.emplace_back(jgeo);
// dummy merc-ctrl
Expand Down
24 changes: 22 additions & 2 deletions goalc/build_actor/jak1/build_actor.h
Original file line number Diff line number Diff line change
Expand Up @@ -153,21 +153,41 @@ struct CollideMesh {
}
};

struct BuildActorParams {
bool gen_collide_mesh = false;
s8 texture_bucket = -1;
s32 texture_level = -1;
s32 joint_channel = -1;
math::Vector4f trans_offset = {0.f, 0.f, 0.f, 1.f};
std::vector<float> lod_dist{};
};

struct ArtJointGeo : ArtElement {
std::vector<Joint> data;
std::vector<CollideMesh> cmeshes;
ResLump lump;
size_t mesh_slot;
s8 texture_bucket;
s32 texture_level;
s32 joint_channel;
math::Vector4f trans_offset;
std::vector<float> lod_dist;

explicit ArtJointGeo(const std::string& name,
std::vector<CollideMesh> cmeshes,
std::vector<Joint>& joints) {
std::vector<Joint>& joints,
const BuildActorParams& params) {
this->name = name + "-lod0";
length = joints.size();
for (auto& joint : joints) {
data.push_back(joint);
}
this->cmeshes = std::move(cmeshes);
this->texture_bucket = params.texture_bucket;
this->texture_level = params.texture_level;
this->joint_channel = params.joint_channel;
this->trans_offset = params.trans_offset;
this->lod_dist = params.lod_dist;
}
void add_res();
size_t generate(DataObjectGenerator& gen);
Expand Down Expand Up @@ -225,5 +245,5 @@ struct ArtGroup : Art {

bool run_build_actor(const std::string& input_model,
const std::string& output_file,
bool gen_collide_mesh);
const BuildActorParams& params);
} // namespace jak1
12 changes: 9 additions & 3 deletions goalc/build_actor/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ int main(int argc, char** argv) {

// game version
std::string game, mdl_name, output_file;
bool gen_collide_mesh = false;
fs::path project_path_override;
jak1::BuildActorParams params;

// path
if (!file_util::setup_project_path(std::nullopt)) {
Expand All @@ -34,7 +34,13 @@ int main(int argc, char** argv) {
app.add_option("-g,--game", game, "Game version (only jak1 for now)")->required();
app.add_option("--proj-path", project_path_override,
"Specify the location of the 'data/' folder");
app.add_flag("-m,--mesh", gen_collide_mesh, "Whether to generate a collide-mesh for this model");
app.add_flag("-m,--mesh", params.gen_collide_mesh, "Whether to generate a collide-mesh for this model");
app.add_option("--texture-bucket", params.texture_bucket,
"Texture bucket to set for this model");
app.add_option("--texture-level", params.texture_level,
"Texture level to set for this model");
app.add_option("--joint-channel", params.joint_channel,
"Amount of joint channels to set for this model");
app.validate_positionals();
CLI11_PARSE(app, argc, argv)

Expand All @@ -55,7 +61,7 @@ int main(int argc, char** argv) {

switch (game_version) {
case GameVersion::Jak1:
jak1::run_build_actor(mdl_name, output_file, gen_collide_mesh);
jak1::run_build_actor(mdl_name, output_file, params);
break;
default:
ASSERT_NOT_REACHED_MSG("unsupported game version");
Expand Down
2 changes: 1 addition & 1 deletion goalc/build_level/common/gltf_mesh_extract.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ void dedup_tie_vertices(TieOutput& data) {
bool prim_needs_tie(const tinygltf::Model& model, const tinygltf::Primitive& prim) {
if (prim.material >= 0) {
auto mat = model.materials.at(prim.material);
return mat.extensions.contains("KHR_materials_specular");
return envmap_is_valid(mat);
}
return false;
}
Expand Down
18 changes: 13 additions & 5 deletions goalc/build_level/jak1/build_level.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
namespace jak1 {
bool run_build_level(const std::string& input_file,
const std::string& bsp_output_file,
const std::string& output_prefix) {
const std::string& output_prefix,
bool gen_fr3) {
auto level_json = parse_commented_json(
file_util::read_text_file(file_util::get_file_path({input_file})), input_file);
LevelFile file{}; // GOAL level file
Expand Down Expand Up @@ -129,8 +130,8 @@ bool run_build_level(const std::string& input_file,

// Add textures and models
// TODO remove hardcoded config settings
if ((level_json.contains("art_groups") && !level_json.at("art_groups").empty()) ||
(level_json.contains("textures") && !level_json.at("textures").empty())) {
if (gen_fr3 && ((level_json.contains("art_groups") && !level_json.at("art_groups").empty()) ||
(level_json.contains("textures") && !level_json.at("textures").empty()))) {
lg::info("Looking for ISO path...");
const auto iso_folder = file_util::get_iso_dir_for_game(GameVersion::Jak1);
lg::info("Found ISO path: {}", iso_folder.string());
Expand Down Expand Up @@ -173,6 +174,11 @@ bool run_build_level(const std::string& input_file,
auto textures_out = file_util::get_jak_project_dir() / "decompiler_out/jak1/textures";
file_util::create_dir_if_needed(textures_out);
db.process_tpages(tex_db, textures_out, config, "");
auto replacements_path = file_util::get_jak_project_dir() / "custom_assets" /
game_version_names[config.game_version] / "texture_replacements";
if (fs::exists(replacements_path)) {
tex_db.replace_textures(replacements_path);
}

std::vector<std::string> processed_art_groups;

Expand Down Expand Up @@ -313,7 +319,7 @@ bool run_build_level(const std::string& input_file,
}

// add custom models to fr3
if (level_json.contains("custom_models") && !level_json.at("custom_models").empty()) {
if (gen_fr3 && level_json.contains("custom_models") && !level_json.at("custom_models").empty()) {
auto models = level_json.at("custom_models").get<std::vector<std::string>>();
for (auto& name : models) {
add_model_to_level(GameVersion::Jak1, name, pc_level);
Expand All @@ -329,8 +335,10 @@ bool run_build_level(const std::string& input_file,
file_util::write_binary_file(save_path, result.data(), result.size());

// Save the PC level
save_pc_data(file.name, pc_level,
if (gen_fr3) {
save_pc_data(file.name, pc_level,
file_util::get_jak_project_dir() / "out" / output_prefix / "fr3");
}

return true;
}
Expand Down
3 changes: 2 additions & 1 deletion goalc/build_level/jak1/build_level.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@
namespace jak1 {
bool run_build_level(const std::string& input_file,
const std::string& bsp_output_file,
const std::string& output_prefix);
const std::string& output_prefix,
bool gen_fr3);
} // namespace jak1
5 changes: 5 additions & 0 deletions goalc/build_level/jak2/LevelFile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ size_t DrawableTreeArray::add_to_object_file(DataObjectGenerator& gen) const {
size_t result = gen.current_offset_bytes();
int num_trees = 0;
num_trees += tfrags.size();
num_trees += ties.size();
gen.add_word(num_trees << 16);
gen.add_word(0);
gen.add_word(0);
Expand All @@ -47,6 +48,10 @@ size_t DrawableTreeArray::add_to_object_file(DataObjectGenerator& gen) const {
// gen.set_word(tree_word++, tfrag.add_to_object_file(gen));
gen.link_word_to_byte(tree_word++, tfrag.add_to_object_file(gen));
}

for (auto& tie : ties) {
gen.link_word_to_byte(tree_word++, tie.add_to_object_file(gen));
}
}

return result;
Expand Down
3 changes: 1 addition & 2 deletions goalc/build_level/jak2/LevelFile.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "goalc/build_level/collide/common/collide_common.h"
#include "goalc/build_level/collide/jak2/collide.h"
#include "goalc/build_level/common/Tfrag.h"
#include "goalc/build_level/common/Tie.h"
#include "goalc/build_level/jak2/Entity.h"
#include "goalc/build_level/jak2/FileInfo.h"

Expand All @@ -17,8 +18,6 @@ struct VisibilityString {
std::vector<u8> bytes;
};

struct DrawableTreeInstanceTie {};

struct DrawableTreeActor {};

struct DrawableTreeInstanceShrub {};
Expand Down
28 changes: 21 additions & 7 deletions goalc/build_level/jak2/build_level.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
namespace jak2 {
bool run_build_level(const std::string& input_file,
const std::string& bsp_output_file,
const std::string& output_prefix) {
const std::string& output_prefix,
bool gen_fr3) {
auto level_json = parse_commented_json(
file_util::read_text_file(file_util::get_file_path({input_file})), input_file);
LevelFile file; // GOAL level file
Expand Down Expand Up @@ -71,6 +72,13 @@ bool run_build_level(const std::string& input_file,
// TFRAG
file.drawable_trees.tfrags.emplace_back("drawable-tree-tfrag", "drawable-inline-array-tfrag");
tfrag_from_gltf(mesh_extract_out.tfrag, pc_level.tfrag_trees[0]);

// TIE
if (!mesh_extract_out.tie.base_draws.empty()) {
file.drawable_trees.ties.emplace_back();
tie_from_gltf(mesh_extract_out.tie, pc_level.tie_trees[0]);
}

pc_level.textures = std::move(tex_pool.textures_by_idx);

// COLLIDE
Expand All @@ -90,8 +98,8 @@ bool run_build_level(const std::string& input_file,

// Add textures and models
// TODO remove hardcoded config settings
if ((level_json.contains("art_groups") && !level_json.at("art_groups").empty()) ||
(level_json.contains("textures") && !level_json.at("textures").empty())) {
if (gen_fr3 && ((level_json.contains("art_groups") && !level_json.at("art_groups").empty()) ||
(level_json.contains("textures") && !level_json.at("textures").empty()))) {
lg::info("Looking for ISO path...");
const auto iso_folder = file_util::get_iso_dir_for_game(GameVersion::Jak2);
lg::info("Found ISO path: {}", iso_folder.string());
Expand Down Expand Up @@ -134,9 +142,14 @@ bool run_build_level(const std::string& input_file,
auto textures_out = file_util::get_jak_project_dir() / "decompiler_out/jak2/textures";
file_util::create_dir_if_needed(textures_out);
db.process_tpages(tex_db, textures_out, config, "");
auto replacements_path = file_util::get_jak_project_dir() / "custom_assets" /
game_version_names[config.game_version] / "texture_replacements";
if (fs::exists(replacements_path)) {
tex_db.replace_textures(replacements_path);
}

// find all art groups used by the custom level in other dgos
if (level_json.contains("art_groups") && !level_json.at("art_groups").empty()) {
if (gen_fr3 && level_json.contains("art_groups") && !level_json.at("art_groups").empty()) {
for (auto& dgo : config.dgo_names) {
std::vector<std::string> processed_art_groups;
// remove "DGO/" prefix
Expand Down Expand Up @@ -191,9 +204,10 @@ bool run_build_level(const std::string& input_file,
}

// Save the PC level
save_pc_data(file.name, pc_level,
file_util::get_jak_project_dir() / "out" / output_prefix / "fr3");

if (gen_fr3) {
save_pc_data(file.name, pc_level,
file_util::get_jak_project_dir() / "out" / output_prefix / "fr3");
}
return true;
}
} // namespace jak2
3 changes: 2 additions & 1 deletion goalc/build_level/jak2/build_level.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@
namespace jak2 {
bool run_build_level(const std::string& input_file,
const std::string& bsp_output_file,
const std::string& output_prefix);
const std::string& output_prefix,
bool gen_fr3);
} // namespace jak2
Loading

0 comments on commit bb262f1

Please sign in to comment.