[tie] support per-proto visibility flags (#2212)

Jak 2 adds a feature to disable protos in TIE. It's used to hide things
like steps for a future mission in ruins, and also to hide the static
version of the tower when it switches to the merc version for the
cutscene:


![image](https://user-images.githubusercontent.com/48171810/218270077-d8c52235-ddbf-4194-80f6-b8aa1eeeb7ec.png)
This commit is contained in:
water111
2023-02-11 12:00:05 -05:00
committed by GitHub
parent 7afa583bff
commit ed38adc2a7
14 changed files with 405 additions and 73 deletions
+3
View File
@@ -209,6 +209,9 @@ void TieTree::serialize(Serializer& ser) {
packed_vertices.serialize(ser);
ser.from_pod_vector(&colors);
bvh.serialize(ser);
ser.from_ptr(&has_per_proto_visibility_toggle);
ser.from_string_vector(&proto_names);
}
void ShrubTree::serialize(Serializer& ser) {
+7 -2
View File
@@ -73,7 +73,7 @@ struct MemoryUsageTracker {
void add(MemoryUsageCategory category, u32 size_bytes) { data[category] += size_bytes; }
};
constexpr int TFRAG3_VERSION = 24;
constexpr int TFRAG3_VERSION = 25;
// These vertices should be uploaded to the GPU at load time and don't change
struct PreloadedVertex {
@@ -188,7 +188,8 @@ struct StripDraw {
struct VisGroup {
u32 num_inds = 0; // number of vertex indices in this group
u32 num_tris = 0; // number of triangles
u32 vis_idx_in_pc_bvh = 0; // the visibility group they belong to (in BVH)
u16 vis_idx_in_pc_bvh = 0; // the visibility group they belong to (in BVH)
u16 tie_proto_idx = 0; // index of tie proto (tie only)
};
std::vector<VisGroup> vis_groups;
@@ -323,6 +324,10 @@ struct TieTree {
std::vector<InstancedStripDraw> instanced_wind_draws;
std::vector<TieWindInstance> wind_instance_info;
// jak 2 and later can toggle on and off visibility per proto by name
bool has_per_proto_visibility_toggle = false;
std::vector<std::string> proto_names;
struct {
std::vector<PreloadedVertex> vertices; // mesh vertices
std::vector<u32> indices;
+11
View File
@@ -156,6 +156,17 @@ class Serializer {
from_raw_data(vec->data(), sizeof(T) * vec->size());
}
void from_string_vector(std::vector<std::string>* vec) {
if (is_saving()) {
save<size_t>(vec->size());
} else {
vec->resize(load<size_t>());
}
for (auto& str : *vec) {
from_str(&str);
}
}
/*!
* Are we saving?
*/
+2 -1
View File
@@ -2053,6 +2053,7 @@ void make_tfrag3_data(std::map<u32, std::vector<GroupedDraw>>& draws,
for (auto& strip : draw.strips) {
tfrag3::StripDraw::VisGroup vgroup;
ASSERT(strip.tfrag_id < UINT16_MAX);
vgroup.vis_idx_in_pc_bvh = strip.tfrag_id; // associate with the tfrag for culling
vgroup.num_inds = strip.verts.size() + 1; // one for the primitive restart!
vgroup.num_tris = strip.verts.size() - 2;
@@ -2231,7 +2232,7 @@ void extract_tfrag(const level_tools::DrawableTreeTfrag* tree,
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;
str.vis_idx_in_pc_bvh = UINT16_MAX;
} else {
str.vis_idx_in_pc_bvh = it->second;
}
+25 -6
View File
@@ -2026,14 +2026,24 @@ DrawMode process_draw_mode(const AdgifInfo& info, bool use_atest, bool use_decal
void add_vertices_and_static_draw(tfrag3::TieTree& tree,
tfrag3::Level& lev,
const TextureDB& tdb,
const std::vector<TieProtoInfo>& protos) {
const std::vector<TieProtoInfo>& protos,
GameVersion version) {
// our current approach for static draws is just to flatten to giant mesh, except for wind stuff.
// this map sorts these two types of draws by texture.
std::unordered_map<u32, std::vector<u32>> static_draws_by_tex;
std::unordered_map<u32, std::vector<u32>> wind_draws_by_tex;
if (version > GameVersion::Jak1) {
tree.has_per_proto_visibility_toggle = true;
}
// loop over all prototypes
for (auto& proto : protos) {
for (size_t proto_idx = 0; proto_idx < protos.size(); proto_idx++) {
const auto& proto = protos[proto_idx];
if (tree.has_per_proto_visibility_toggle) {
tree.proto_names.push_back(proto.name);
}
if (proto.uses_generic) {
// generic ties go through generic
continue;
@@ -2220,7 +2230,15 @@ void add_vertices_and_static_draw(tfrag3::TieTree& tree,
// now we have a draw, time to add vertices
tfrag3::StripDraw::VisGroup vgroup;
vgroup.vis_idx_in_pc_bvh = inst.vis_id; // associate with the instance for culling
ASSERT(inst.vis_id < UINT16_MAX);
vgroup.vis_idx_in_pc_bvh = inst.vis_id; // associate with the instance for culling
// only bother with tie proto idx if we use it
if (tree.has_per_proto_visibility_toggle) {
ASSERT(proto_idx < UINT16_MAX);
vgroup.tie_proto_idx = proto_idx;
}
vgroup.num_inds = strip.verts.size() + 1; // one for the primitive restart!
vgroup.num_tris = strip.verts.size() - 2;
draw_to_add_to->num_triangles += strip.verts.size() - 2;
@@ -2284,7 +2302,8 @@ void merge_groups(std::vector<tfrag3::StripDraw::VisGroup>& grps) {
std::vector<tfrag3::StripDraw::VisGroup> result;
result.push_back(grps.at(0));
for (size_t i = 1; i < grps.size(); i++) {
if (grps[i].vis_idx_in_pc_bvh == result.back().vis_idx_in_pc_bvh) {
if (grps[i].vis_idx_in_pc_bvh == result.back().vis_idx_in_pc_bvh &&
grps[i].tie_proto_idx == result.back().tie_proto_idx) {
result.back().num_tris += grps[i].num_tris;
result.back().num_inds += grps[i].num_inds;
} else {
@@ -2367,14 +2386,14 @@ void extract_tie(const level_tools::DrawableTreeInstanceTie* tree,
auto full_palette = make_big_palette(info);
// create draws
add_vertices_and_static_draw(this_tree, out, tex_db, info);
add_vertices_and_static_draw(this_tree, out, tex_db, info, version);
// remap vis indices and merge
for (auto& draw : this_tree.static_draws) {
for (auto& str : draw.vis_groups) {
auto it = instance_parents.find(str.vis_idx_in_pc_bvh);
if (it == instance_parents.end()) {
str.vis_idx_in_pc_bvh = UINT32_MAX;
str.vis_idx_in_pc_bvh = UINT16_MAX;
} else {
str.vis_idx_in_pc_bvh = it->second;
}
+101 -11
View File
@@ -2,6 +2,7 @@
#include "common/global_profiler/GlobalProfiler.h"
#include "common/log/log.h"
#include "common/util/Assert.h"
#include "third-party/imgui/imgui.h"
@@ -120,6 +121,11 @@ void Tie3::update_load(const LevelData* loader_data) {
}
}
lod_tree[l_tree].has_proto_visibility = tree.has_per_proto_visibility_toggle;
if (tree.has_per_proto_visibility_toggle) {
lod_tree[l_tree].proto_visibility.init(tree.proto_names);
}
glActiveTexture(GL_TEXTURE10);
glGenTextures(1, &lod_tree[l_tree].time_of_day_texture);
glBindTexture(GL_TEXTURE_1D, lod_tree[l_tree].time_of_day_texture);
@@ -139,6 +145,7 @@ void Tie3::update_load(const LevelData* loader_data) {
m_wind_vectors.resize(4 * max_wind_idx + 4); // 4x u32's per wind.
m_cache.draw_idx_temp.resize(max_draws);
m_cache.index_temp.resize(max_inds);
ASSERT(time_of_day_count <= TIME_OF_DAY_COLOR_COUNT);
}
@@ -361,7 +368,14 @@ void Tie3::render(DmaFollower& dma, SharedRenderState* render_state, ScopedProfi
auto wind_data = dma.read_and_advance();
ASSERT(wind_data.size_bytes == sizeof(WindWork));
memcpy(&m_wind_data, wind_data.data, sizeof(WindWork));
} else {
}
const u8* proto_vis_data = nullptr;
size_t proto_vis_data_size = 0;
if (render_state->version == GameVersion::Jak2) {
auto proto_mask_data = dma.read_and_advance();
proto_vis_data = proto_mask_data.data;
proto_vis_data_size = proto_mask_data.size_bytes;
}
while (dma.current_tag_offset() != render_state->next_bucket) {
@@ -390,20 +404,22 @@ void Tie3::render(DmaFollower& dma, SharedRenderState* render_state, ScopedProfi
m_has_level = setup_for_level(m_pc_port_data.level_name, render_state);
}
render_all_trees(lod(), settings, render_state, prof);
render_all_trees(lod(), settings, render_state, prof, proto_vis_data, proto_vis_data_size);
}
void Tie3::render_all_trees(int geom,
const TfragRenderSettings& settings,
SharedRenderState* render_state,
ScopedProfilerNode& prof) {
ScopedProfilerNode& prof,
const u8* proto_vis_data,
size_t proto_vis_data_size) {
Timer all_tree_timer;
if (m_override_level && m_pending_user_level) {
m_has_level = setup_for_level(*m_pending_user_level, render_state);
m_pending_user_level = {};
}
for (u32 i = 0; i < m_trees[geom].size(); i++) {
render_tree(i, geom, settings, render_state, prof);
render_tree(i, geom, settings, render_state, prof, proto_vis_data, proto_vis_data_size);
}
m_all_tree_time.add(all_tree_timer.getSeconds());
}
@@ -523,7 +539,9 @@ void Tie3::render_tree(int idx,
int geom,
const TfragRenderSettings& settings,
SharedRenderState* render_state,
ScopedProfilerNode& prof) {
ScopedProfilerNode& prof,
const u8* proto_vis_data,
size_t proto_vis_data_size) {
// reset perf
Timer tree_timer;
auto& tree = m_trees.at(geom).at(idx);
@@ -540,6 +558,11 @@ void Tie3::render_tree(int idx,
m_color_result.resize(tree.colors->size());
}
// update proto vis mask
if (proto_vis_data) {
tree.proto_visibility.update(proto_vis_data, proto_vis_data_size);
}
Timer interp_timer;
if (m_use_fast_time_of_day) {
interp_time_of_day_fast(settings.itimes, tree.tod_cache, m_color_result.data());
@@ -588,9 +611,15 @@ void Tie3::render_tree(int idx,
make_all_visible_index_list(m_cache.draw_idx_temp.data(), m_cache.index_temp.data(),
*tree.draws, tree.index_data, &num_tris);
} else {
idx_buffer_size = make_index_list_from_vis_string(
m_cache.draw_idx_temp.data(), m_cache.index_temp.data(), *tree.draws, m_cache.vis_temp,
tree.index_data, &num_tris);
if (tree.has_proto_visibility) {
idx_buffer_size = make_index_list_from_vis_and_proto_string(
m_cache.draw_idx_temp.data(), m_cache.index_temp.data(), *tree.draws, m_cache.vis_temp,
tree.proto_visibility.vis_flags, tree.index_data, &num_tris);
} else {
idx_buffer_size = make_index_list_from_vis_string(
m_cache.draw_idx_temp.data(), m_cache.index_temp.data(), *tree.draws, m_cache.vis_temp,
tree.index_data, &num_tris);
}
}
glBufferData(GL_ELEMENT_ARRAY_BUFFER, idx_buffer_size * sizeof(u32), m_cache.index_temp.data(),
@@ -606,9 +635,17 @@ void Tie3::render_tree(int idx,
tree.perf.index_time.add(index_timer.getSeconds());
} else {
Timer index_timer;
num_tris = make_multidraws_from_vis_string(
m_cache.multidraw_offset_per_stripdraw.data(), m_cache.multidraw_count_buffer.data(),
m_cache.multidraw_index_offset_buffer.data(), *tree.draws, m_cache.vis_temp);
if (tree.has_proto_visibility) {
num_tris = make_multidraws_from_vis_and_proto_string(
m_cache.multidraw_offset_per_stripdraw.data(), m_cache.multidraw_count_buffer.data(),
m_cache.multidraw_index_offset_buffer.data(), *tree.draws, m_cache.vis_temp,
tree.proto_visibility.vis_flags);
} else {
num_tris = make_multidraws_from_vis_string(
m_cache.multidraw_offset_per_stripdraw.data(), m_cache.multidraw_count_buffer.data(),
m_cache.multidraw_index_offset_buffer.data(), *tree.draws, m_cache.vis_temp);
}
tree.perf.index_time.add(index_timer.getSeconds());
}
}
@@ -731,6 +768,7 @@ void Tie3::draw_debug_window() {
ImGui::Text("draw: %d", perf.draws);
ImGui::Text("wind draw: %d", perf.wind_draws);
ImGui::Text("total: %.2f", perf.tree_time.get());
ImGui::Text("proto vis: %.2f", perf.proto_vis_time.get() * 1000.f);
ImGui::Text("cull: %.2f index: %.2f tod: %.2f setup: %.2f draw: %.2f",
perf.cull_time.get() * 1000.f, perf.index_time.get() * 1000.f,
perf.tod_time.get() * 1000.f, perf.setup_time.get() * 1000.f,
@@ -739,3 +777,55 @@ void Tie3::draw_debug_window() {
}
ImGui::Text("All trees: %.2f", 1000.f * m_all_tree_time.get());
}
void TieProtoVisibility::init(const std::vector<std::string>& names) {
vis_flags.resize(names.size());
for (auto& x : vis_flags) {
x = 1;
}
all_visible = true;
name_to_idx.clear();
size_t i = 0;
for (auto& name : names) {
name_to_idx[name].push_back(i++);
}
}
void TieProtoVisibility::update(const u8* data, size_t size) {
char name_buffer[256]; // ??
if (!all_visible) {
for (auto& x : vis_flags) {
x = 1;
}
all_visible = true;
}
const u8* end = data + size;
while (true) {
int name_idx = 0;
while (*data) {
name_buffer[name_idx++] = *data;
data++;
}
if (name_idx) {
ASSERT(name_idx < 254);
name_buffer[name_idx] = '\0';
const auto& it = name_to_idx.find(name_buffer);
if (it != name_to_idx.end()) {
all_visible = false;
for (auto x : name_to_idx.at(name_buffer)) {
vis_flags[x] = 0;
}
}
}
while (*data == 0) {
if (data >= end) {
return;
}
data++;
}
}
}
@@ -9,6 +9,16 @@
#include "game/graphics/opengl_renderer/background/background_common.h"
#include "game/graphics/pipelines/opengl.h"
struct TieProtoVisibility {
void init(const std::vector<std::string>& names);
void update(const u8* data, size_t size);
std::vector<u8> vis_flags;
std::unordered_map<std::string, std::vector<u32>> name_to_idx;
bool all_visible = true;
};
class Tie3 : public BucketRenderer {
public:
Tie3(const std::string& name, int my_id, int level_id);
@@ -19,12 +29,16 @@ class Tie3 : public BucketRenderer {
void render_all_trees(int geom,
const TfragRenderSettings& settings,
SharedRenderState* render_state,
ScopedProfilerNode& prof);
ScopedProfilerNode& prof,
const u8* proto_vis_data,
size_t proto_vis_data_size);
void render_tree(int idx,
int geom,
const TfragRenderSettings& settings,
SharedRenderState* render_state,
ScopedProfilerNode& prof);
ScopedProfilerNode& prof,
const u8* proto_vis_data,
size_t proto_vis_data_size);
bool setup_for_level(const std::string& str, SharedRenderState* render_state);
struct WindWork {
@@ -70,12 +84,16 @@ class Tie3 : public BucketRenderer {
GLuint wind_vertex_index_buffer;
std::vector<u32> wind_vertex_index_offsets;
bool has_proto_visibility = false;
TieProtoVisibility proto_visibility;
struct {
u32 draws = 0;
u32 wind_draws = 0;
Filtered<float> cull_time;
Filtered<float> index_time;
Filtered<float> tod_time;
Filtered<float> proto_vis_time;
Filtered<float> setup_time;
Filtered<float> draw_time;
Filtered<float> tree_time;
@@ -516,7 +516,64 @@ u32 make_multidraws_from_vis_string(std::pair<int, int>* draw_ptrs_out,
u64 run_start = 0;
for (auto& grp : draw.vis_groups) {
sanity_check += grp.num_inds;
bool vis = grp.vis_idx_in_pc_bvh == 0xffffffff || vis_data[grp.vis_idx_in_pc_bvh];
bool vis = grp.vis_idx_in_pc_bvh == UINT16_MAX || vis_data[grp.vis_idx_in_pc_bvh];
if (vis) {
num_tris += grp.num_tris;
}
if (building_run) {
if (!vis) {
building_run = false;
counts_out[md_idx] = iidx - run_start;
index_offsets_out[md_idx] = (void*)(run_start * sizeof(u32));
ds.second++;
md_idx++;
}
} else {
if (vis) {
building_run = true;
run_start = iidx;
}
}
iidx += grp.num_inds;
}
if (building_run) {
building_run = false;
counts_out[md_idx] = iidx - run_start;
index_offsets_out[md_idx] = (void*)(run_start * sizeof(u32));
ds.second++;
md_idx++;
}
draw_ptrs_out[i] = ds;
}
return num_tris;
}
u32 make_multidraws_from_vis_and_proto_string(std::pair<int, int>* draw_ptrs_out,
GLsizei* counts_out,
void** index_offsets_out,
const std::vector<tfrag3::StripDraw>& draws,
const std::vector<u8>& vis_data,
const std::vector<u8>& proto_vis_data) {
u64 md_idx = 0;
u32 num_tris = 0;
u32 sanity_check = 0;
for (size_t i = 0; i < draws.size(); i++) {
const auto& draw = draws[i];
u64 iidx = draw.unpacked.idx_of_first_idx_in_full_buffer;
ASSERT(sanity_check == iidx);
std::pair<int, int> ds;
ds.first = md_idx;
ds.second = 0;
bool building_run = false;
u64 run_start = 0;
for (auto& grp : draw.vis_groups) {
sanity_check += grp.num_inds;
bool vis = (grp.vis_idx_in_pc_bvh == UINT16_MAX || vis_data[grp.vis_idx_in_pc_bvh]) &&
proto_vis_data[grp.tie_proto_idx];
if (vis) {
num_tris += grp.num_tris;
}
@@ -569,7 +626,64 @@ u32 make_index_list_from_vis_string(std::pair<int, int>* group_out,
int run_start_out = 0;
int run_start_in = 0;
for (auto& grp : draw.vis_groups) {
bool vis = grp.vis_idx_in_pc_bvh == 0xffffffff || vis_data[grp.vis_idx_in_pc_bvh];
bool vis = grp.vis_idx_in_pc_bvh == UINT16_MAX || vis_data[grp.vis_idx_in_pc_bvh];
if (vis) {
num_tris += grp.num_tris;
}
if (building_run) {
if (vis) {
idx_buffer_ptr += grp.num_inds;
} else {
building_run = false;
memcpy(&idx_out[run_start_out],
idx_in + draw.unpacked.idx_of_first_idx_in_full_buffer + run_start_in,
(idx_buffer_ptr - run_start_out) * sizeof(u32));
}
} else {
if (vis) {
building_run = true;
run_start_out = idx_buffer_ptr;
run_start_in = vtx_idx;
idx_buffer_ptr += grp.num_inds;
}
}
vtx_idx += grp.num_inds;
}
if (building_run) {
memcpy(&idx_out[run_start_out],
idx_in + draw.unpacked.idx_of_first_idx_in_full_buffer + run_start_in,
(idx_buffer_ptr - run_start_out) * sizeof(u32));
}
ds.second = idx_buffer_ptr - ds.first;
group_out[i] = ds;
}
*num_tris_out = num_tris;
return idx_buffer_ptr;
}
u32 make_index_list_from_vis_and_proto_string(std::pair<int, int>* group_out,
u32* idx_out,
const std::vector<tfrag3::StripDraw>& draws,
const std::vector<u8>& vis_data,
const std::vector<u8>& proto_vis_data,
const u32* idx_in,
u32* num_tris_out) {
int idx_buffer_ptr = 0;
u32 num_tris = 0;
for (size_t i = 0; i < draws.size(); i++) {
const auto& draw = draws[i];
int vtx_idx = 0;
std::pair<int, int> ds;
ds.first = idx_buffer_ptr;
bool building_run = false;
int run_start_out = 0;
int run_start_in = 0;
for (auto& grp : draw.vis_groups) {
bool vis = (grp.vis_idx_in_pc_bvh == UINT16_MAX || vis_data[grp.vis_idx_in_pc_bvh]) &&
proto_vis_data[grp.tie_proto_idx];
if (vis) {
num_tris += grp.num_tris;
}
@@ -99,4 +99,19 @@ u32 make_index_list_from_vis_string(std::pair<int, int>* group_out,
u32 make_all_visible_index_list(std::pair<int, int>* group_out,
u32* idx_out,
const std::vector<tfrag3::ShrubDraw>& draws,
const u32* idx_in);
const u32* idx_in);
u32 make_multidraws_from_vis_and_proto_string(std::pair<int, int>* draw_ptrs_out,
GLsizei* counts_out,
void** index_offsets_out,
const std::vector<tfrag3::StripDraw>& draws,
const std::vector<u8>& vis_data,
const std::vector<u8>& proto_vis_data);
u32 make_index_list_from_vis_and_proto_string(std::pair<int, int>* group_out,
u32* idx_out,
const std::vector<tfrag3::StripDraw>& draws,
const std::vector<u8>& vis_data,
const std::vector<u8>& proto_vis_data,
const u32* idx_in,
u32* num_tris_out);
+47 -45
View File
@@ -415,61 +415,63 @@ void Loader::update(TexturePool& texture_pool) {
Timer unload_timer;
if ((int)m_loaded_tfrag3_levels.size() >= m_max_levels) {
auto to_unload = get_most_unloadable_level();
auto& lev = m_loaded_tfrag3_levels.at(*to_unload);
std::unique_lock<std::mutex> lk(texture_pool.mutex());
fmt::print("------------------------- PC unloading {}\n", *to_unload);
for (size_t i = 0; i < lev->level->textures.size(); i++) {
auto& tex = lev->level->textures[i];
if (tex.load_to_pool) {
texture_pool.unload_texture(PcTextureId::from_combo_id(tex.combo_id),
lev->textures.at(i));
if (to_unload) {
auto& lev = m_loaded_tfrag3_levels.at(*to_unload);
std::unique_lock<std::mutex> lk(texture_pool.mutex());
fmt::print("------------------------- PC unloading {}\n", *to_unload);
for (size_t i = 0; i < lev->level->textures.size(); i++) {
auto& tex = lev->level->textures[i];
if (tex.load_to_pool) {
texture_pool.unload_texture(PcTextureId::from_combo_id(tex.combo_id),
lev->textures.at(i));
}
}
}
lk.unlock();
for (auto tex : lev->textures) {
if (EXTRA_TEX_DEBUG) {
for (auto& slot : texture_pool.all_textures()) {
if (slot.source) {
ASSERT(slot.gpu_texture != tex);
} else {
ASSERT(slot.gpu_texture != tex);
lk.unlock();
for (auto tex : lev->textures) {
if (EXTRA_TEX_DEBUG) {
for (auto& slot : texture_pool.all_textures()) {
if (slot.source) {
ASSERT(slot.gpu_texture != tex);
} else {
ASSERT(slot.gpu_texture != tex);
}
}
}
glBindTexture(GL_TEXTURE_2D, tex);
glDeleteTextures(1, &tex);
}
glBindTexture(GL_TEXTURE_2D, tex);
glDeleteTextures(1, &tex);
}
for (auto& tie_geo : lev->tie_data) {
for (auto& tie_tree : tie_geo) {
glDeleteBuffers(1, &tie_tree.vertex_buffer);
if (tie_tree.has_wind) {
glDeleteBuffers(1, &tie_tree.wind_indices);
for (auto& tie_geo : lev->tie_data) {
for (auto& tie_tree : tie_geo) {
glDeleteBuffers(1, &tie_tree.vertex_buffer);
if (tie_tree.has_wind) {
glDeleteBuffers(1, &tie_tree.wind_indices);
}
glDeleteBuffers(1, &tie_tree.index_buffer);
}
glDeleteBuffers(1, &tie_tree.index_buffer);
}
}
for (auto& tfrag_geo : lev->tfrag_vertex_data) {
for (auto& tfrag_buff : tfrag_geo) {
glDeleteBuffers(1, &tfrag_buff);
for (auto& tfrag_geo : lev->tfrag_vertex_data) {
for (auto& tfrag_buff : tfrag_geo) {
glDeleteBuffers(1, &tfrag_buff);
}
}
glDeleteBuffers(1, &lev->collide_vertices);
glDeleteBuffers(1, &lev->merc_vertices);
glDeleteBuffers(1, &lev->merc_indices);
for (auto& model : lev->level->merc_data.models) {
auto& mercs = m_all_merc_models.at(model.name);
MercRef ref{&model, lev->load_id};
auto it = std::find(mercs.begin(), mercs.end(), ref);
ASSERT_MSG(it != mercs.end(), fmt::format("missing merc: {}\n", model.name));
mercs.erase(it);
}
m_loaded_tfrag3_levels.erase(*to_unload);
}
glDeleteBuffers(1, &lev->collide_vertices);
glDeleteBuffers(1, &lev->merc_vertices);
glDeleteBuffers(1, &lev->merc_indices);
for (auto& model : lev->level->merc_data.models) {
auto& mercs = m_all_merc_models.at(model.name);
MercRef ref{&model, lev->load_id};
auto it = std::find(mercs.begin(), mercs.end(), ref);
ASSERT_MSG(it != mercs.end(), fmt::format("missing merc: {}\n", model.name));
mercs.erase(it);
}
m_loaded_tfrag3_levels.erase(*to_unload);
}
if (unload_timer.getMs() > 5.f) {
+1
View File
@@ -515,6 +515,7 @@ s32 format_impl_jak2(uint64_t* args) {
default:
MsgErr("format: unknown code 0x%02x\n", format_ptr[1]);
MsgErr("input was %s\n", format_cstring);
ASSERT(false);
break;
}
@@ -58,6 +58,58 @@
;; definition for function draw-inline-array-prototype-tie-asm
;; ERROR: function was not converted to expressions. Cannot decompile.
(defun pc-add-tie-vis-mask ((lev level) (dma-buf dma-buffer))
"Add data so Tie3.cpp can hide protos."
(let ((packet (the-as dma-packet (-> dma-buf base))))
(set! (-> packet vif0) (new 'static 'vif-tag))
(set! (-> packet vif1) (new 'static 'vif-tag :cmd (vif-cmd pc-port)))
(set! (-> dma-buf base) (the pointer (&+ packet 16)))
(let ((lev-trees (-> lev bsp drawable-trees))
(data-ptr (the (pointer uint8) (-> dma-buf base)))
)
(dotimes (tree-idx (-> lev-trees length))
(let ((tree (-> lev-trees data tree-idx)))
(when (= (-> tree type) drawable-tree-instance-tie)
(let* ((tie-tree (the drawable-tree-instance-tie tree))
(protos (-> tie-tree prototypes prototype-array-tie))
)
(dotimes (i (-> protos length))
(let ((proto (-> protos array-data i)))
(when (logtest? (-> proto flags) (prototype-flags visible))
;; invisible!
;(format 0 "invis: ~A~%" (-> proto name))
(let ((src (-> proto name data)))
(while (nonzero? (-> src))
(set! (-> data-ptr) (-> src))
(&+! src 1)
(&+! data-ptr 1)
)
(set! (-> data-ptr) 0)
(&+! data-ptr 1)
)
)
)
)
)
)
)
)
;; align
(while (nonzero? (logand data-ptr #xf))
(set! (-> data-ptr) 0)
(&+! data-ptr 1)
)
(set! (-> packet dma) (new 'static 'dma-tag
:id (dma-tag-id cnt)
:qwc (/ (&- data-ptr (-> dma-buf base)) 16))
)
(set! (-> dma-buf base) data-ptr)
#f
)
)
)
(defun instance-tie-patch-buckets ((arg0 dma-buffer) (arg1 level))
; (when (logtest? (-> *display* vu1-enable-user) (vu1-renderer-mask tie))
; (when (nonzero? (-> *prototype-tie-work* scissor-count))
@@ -167,6 +219,7 @@
; )
; (&+! (-> v1-42 base) 16)
(add-pc-tfrag3-data v1-42 arg1)
(pc-add-tie-vis-mask arg1 v1-42)
(let ((a3-16 (-> v1-42 base)))
(let ((a0-20 (the-as dma-packet (-> v1-42 base))))
(set! (-> a0-20 dma) (new 'static 'dma-tag :id (dma-tag-id next)))
+1 -1
View File
@@ -1117,7 +1117,7 @@
(else
(format
0
"ERROR: <asg> ~A in spool anim loop for ~A ~D, but not loaded.~"
"ERROR: <asg> ~A in spool anim loop for ~A ~D, but not loaded.~%" ;; fixed missing %.
self
(-> gp-0 anim name)
(-> gp-0 part)
+2 -2
View File
@@ -556,12 +556,12 @@ void extract(const Input& in,
auto& grp = draw.vis_groups.emplace_back();
grp.num_inds += prim_indices.size();
grp.num_tris += draw.num_triangles;
grp.vis_idx_in_pc_bvh = UINT32_MAX;
grp.vis_idx_in_pc_bvh = UINT16_MAX;
} else {
auto& grp = draw.vis_groups.back();
grp.num_inds += prim_indices.size();
grp.num_tris += draw.num_triangles;
grp.vis_idx_in_pc_bvh = UINT32_MAX;
grp.vis_idx_in_pc_bvh = UINT16_MAX;
}
draw.plain_indices.insert(draw.plain_indices.end(), prim_indices.begin(),