custom levels: add initial support for ambients (#2173)

This commit is contained in:
Hat Kid
2023-01-31 01:21:26 +01:00
committed by GitHub
parent fff3a2d872
commit 7914c723dc
9 changed files with 186 additions and 10 deletions
+3 -1
View File
@@ -33,7 +33,9 @@
// The base actor id for your custom level. If you have multiple levels this should be unique!
"base_id": 100,
"ambients": [],
"actors" : [
{
"trans": [-21.6238, 20.0496, 17.1191], // translation
+1
View File
@@ -16,6 +16,7 @@ add_library(compiler
build_level/LevelFile.cpp
build_level/ResLump.cpp
build_level/Tfrag.cpp
build_level/drawable_ambient.cpp
compiler/Compiler.cpp
compiler/Env.cpp
compiler/Val.cpp
+81
View File
@@ -30,6 +30,18 @@ size_t EntityActor::generate(DataObjectGenerator& gen) const {
return result;
}
size_t EntityAmbient::generate(DataObjectGenerator& gen) const {
size_t result = res_lump.generate_header(gen, "entity-ambient");
for (size_t i = 0; i < 4; i++) {
gen.add_word_float(trans[i]);
}
ASSERT(vis_id < UINT16_MAX);
gen.add_word(aid);
gen.add_word(vis_id);
res_lump.generate_tag_list_and_data(gen, result);
return result;
}
size_t generate_drawable_actor(DataObjectGenerator& gen,
const EntityActor& actor,
size_t actor_loc) {
@@ -46,6 +58,21 @@ size_t generate_drawable_actor(DataObjectGenerator& gen,
return result;
}
size_t generate_drawable_ambient(DataObjectGenerator& gen,
const EntityAmbient& ambient,
size_t ambient_loc) {
gen.align_to_basic();
gen.add_type_tag("drawable-ambient"); // 0
size_t result = gen.current_offset_bytes();
gen.add_word(ambient.vis_id); // 4
gen.link_word_to_byte(gen.add_word(0), ambient_loc); // 8
gen.add_word(0); // 12
for (int i = 0; i < 4; i++) {
gen.add_word_float(ambient.bsphere[i]); // 16, 20, 24, 28
}
return result;
}
size_t generate_inline_array_actors(DataObjectGenerator& gen,
const std::vector<EntityActor>& actors) {
std::vector<size_t> actor_locs;
@@ -74,6 +101,30 @@ size_t generate_inline_array_actors(DataObjectGenerator& gen,
return result;
}
size_t generate_inline_array_ambients(DataObjectGenerator& gen,
const std::vector<EntityAmbient>& ambients) {
std::vector<size_t> ambient_locs;
for (auto& ambient : ambients) {
ambient_locs.push_back(ambient.generate(gen));
}
gen.align_to_basic();
gen.add_type_tag("drawable-inline-array-ambient"); // 0
size_t result = gen.current_offset_bytes();
ASSERT(ambients.size() < UINT16_MAX);
gen.add_word(ambients.size() << 16); // 4
gen.add_word(0);
gen.add_word(0);
gen.add_word(0);
gen.add_word(0);
gen.add_word(0);
gen.add_word(0);
ASSERT((gen.current_offset_bytes() % 16) == 0);
for (size_t i = 0; i < ambients.size(); i++) {
generate_drawable_ambient(gen, ambients[i], ambient_locs[i]);
}
return result;
}
namespace {
math::Vector4f vectorm3_from_json(const nlohmann::json& json) {
ASSERT(json.size() == 3);
@@ -143,6 +194,36 @@ std::unique_ptr<Res> res_from_json_array(const std::string& name,
}
} // namespace
void add_ambients_from_json(const nlohmann::json& json,
std::vector<EntityAmbient>& ambient_list,
u32 base_aid) {
for (const auto& ambient_json : json) {
auto& ambient = ambient_list.emplace_back();
ambient.aid = ambient_json.value("aid", base_aid + ambient_list.size());
ambient.trans = vectorm4_from_json(ambient_json.at("trans"));
ambient.bsphere = vectorm4_from_json(ambient_json.at("bsphere"));
if (ambient_json.find("lump") != ambient_json.end()) {
for (auto [key, value] : ambient_json.at("lump").items()) {
if (value.is_string()) {
std::string value_string = value.get<std::string>();
if (value_string.size() > 0 && value_string[0] == '\'') {
ambient.res_lump.add_res(
std::make_unique<ResSymbol>(key, value_string.substr(1), -1000000000.0000));
} else {
ambient.res_lump.add_res(
std::make_unique<ResString>(key, value_string, -1000000000.0000));
}
continue;
}
if (value.is_array()) {
ambient.res_lump.add_res(res_from_json_array(key, value));
}
}
}
ambient.res_lump.sort_res();
}
}
void add_actors_from_json(const nlohmann::json& json,
std::vector<EntityActor>& actor_list,
u32 base_aid) {
+15
View File
@@ -28,9 +28,24 @@ struct EntityActor {
size_t generate(DataObjectGenerator& gen) const;
};
struct EntityAmbient {
ResLump res_lump;
u32 aid = 0;
math::Vector4f trans;
u32 vis_id = 0;
math::Vector4f bsphere;
size_t generate(DataObjectGenerator& gen) const;
};
size_t generate_inline_array_actors(DataObjectGenerator& gen,
const std::vector<EntityActor>& actors);
size_t generate_inline_array_ambients(DataObjectGenerator& gen,
const std::vector<EntityAmbient>& ambients);
void add_ambients_from_json(const nlohmann::json& json,
std::vector<EntityAmbient>& ambient_list,
u32 base_aid);
void add_actors_from_json(const nlohmann::json& json,
std::vector<EntityActor>& actor_list,
u32 base_aid);
+15 -2
View File
@@ -2,7 +2,10 @@
#include "goalc/data_compiler/DataObjectGenerator.h"
size_t DrawableTreeArray::add_to_object_file(DataObjectGenerator& gen) const {
// TODO find better way to pass the ambient array
size_t DrawableTreeArray::add_to_object_file(DataObjectGenerator& gen,
size_t ambient_count,
size_t ambient_arr_slot) const {
/*
(deftype drawable-tree-array (drawable-group)
((trees drawable-tree 1 :offset 32 :score 100))
@@ -24,6 +27,7 @@ size_t DrawableTreeArray::add_to_object_file(DataObjectGenerator& gen) const {
int num_trees = 0;
num_trees += tfrags.size();
num_trees += collides.size();
num_trees += ambients.size();
gen.add_word(num_trees << 16);
gen.add_word(0);
gen.add_word(0);
@@ -51,6 +55,11 @@ size_t DrawableTreeArray::add_to_object_file(DataObjectGenerator& gen) const {
for (auto& collide : collides) {
gen.link_word_to_byte(tree_word++, collide.add_to_object_file(gen));
}
for (auto& ambients : ambients) {
gen.link_word_to_byte(tree_word++,
ambients.add_to_object_file(gen, ambient_count, ambient_arr_slot));
}
}
return result;
@@ -78,11 +87,14 @@ std::vector<u8> LevelFile::save_object_file() const {
auto file_info_slot = info.add_to_object_file(gen);
gen.link_word_to_byte(1, file_info_slot);
auto ambient_arr_slot = generate_inline_array_ambients(gen, ambients);
//(bsphere vector :inline :offset-assert 16)
//(all-visible-list (pointer uint16) :offset-assert 32)
//(visible-list-length int32 :offset-assert 36)
//(drawable-trees drawable-tree-array :offset-assert 40)
gen.link_word_to_byte(40 / 4, drawable_trees.add_to_object_file(gen));
gen.link_word_to_byte(40 / 4,
drawable_trees.add_to_object_file(gen, ambients.size(), ambient_arr_slot));
//(pat pointer :offset-assert 44)
//(pat-length int32 :offset-assert 48)
//(texture-remap-table (pointer uint64) :offset-assert 52)
@@ -105,6 +117,7 @@ std::vector<u8> LevelFile::save_object_file() const {
//(boxes box8s-array :offset-assert 148)
//(current-bsp-back-flags uint32 :offset-assert 152)
//(ambients drawable-inline-array-ambient :offset-assert 156)
gen.link_word_to_byte(156 / 4, ambient_arr_slot);
//(unk-data-4 float :offset-assert 160)
//(unk-data-5 float :offset-assert 164)
//(adgifs adgif-shader-array :offset-assert 168)
+8 -7
View File
@@ -13,6 +13,7 @@
#include "goalc/build_level/collide_common.h"
#include "goalc/build_level/collide_drawable.h"
#include "goalc/build_level/collide_pack.h"
#include "goalc/build_level/drawable_ambient.h"
struct VisibilityString {
std::vector<u8> bytes;
@@ -22,8 +23,6 @@ struct DrawableTreeInstanceTie {};
struct DrawableTreeActor {};
struct DrawableTreeAmbient {};
struct DrawableTreeInstanceShrub {};
struct DrawableTreeArray {
@@ -33,7 +32,9 @@ struct DrawableTreeArray {
std::vector<DrawableTreeCollideFragment> collides;
std::vector<DrawableTreeAmbient> ambients;
std::vector<DrawableTreeInstanceShrub> shrubs;
size_t add_to_object_file(DataObjectGenerator& gen) const;
size_t add_to_object_file(DataObjectGenerator& gen,
size_t ambient_count,
size_t ambient_arr_slot) const;
};
struct TextureRemap {};
@@ -48,9 +49,9 @@ struct BspNode {};
struct Box8s {};
struct DrawableAmbient {};
struct DrawableInlineArrayAmbient {};
struct DrawableInlineArrayAmbient {
std::vector<EntityAmbient> ambients;
};
struct AdgifShaderArray {};
@@ -115,7 +116,7 @@ struct LevelFile {
// zero
// (ambients drawable-inline-array-ambient :offset-assert 156)
DrawableInlineArrayAmbient ambients;
std::vector<EntityAmbient> ambients;
// (unk-data-4 float :offset-assert 160)
float close_subdiv = 0;
+5
View File
@@ -72,6 +72,11 @@ bool run_build_level(const std::string& input_file,
std::vector<EntityActor> actors;
add_actors_from_json(level_json.at("actors"), actors, level_json.value("base_id", 1234));
file.actors = std::move(actors);
// ambients
std::vector<EntityAmbient> ambients;
add_ambients_from_json(level_json.at("ambients"), ambients, level_json.value("base_id", 12345));
file.ambients = std::move(ambients);
auto& ambient_drawable_tree = file.drawable_trees.ambients.emplace_back();
// cameras
// nodes
// boxes
+41
View File
@@ -0,0 +1,41 @@
#include "drawable_ambient.h"
#include "goalc/data_compiler/DataObjectGenerator.h"
/*
(deftype drawable-group (drawable)
((length int16 :offset 6)
(data drawable 1 :offset-assert 32)
)
(:methods
(new (symbol type int) _type_)
)
:flag-assert #x1200000024
)
(deftype drawable-tree (drawable-group)
()
:flag-assert #x1200000024
)
(deftype drawable-inline-array (drawable)
((length int16 :offset 6) ;; this is kinda weird.
)
:method-count-assert 18
:size-assert #x20
:flag-assert #x1200000020
)
*/
size_t DrawableTreeAmbient::add_to_object_file(DataObjectGenerator& gen,
size_t ambient_count,
size_t ambient_arr_slot) const {
gen.align_to_basic();
gen.add_type_tag("drawable-tree-ambient");
size_t result = gen.current_offset_bytes();
gen.add_word(ambient_count << 16); // 4, 6
gen.add_word(0); // 8
gen.add_word(0); // 12
gen.add_word(0); // 16
gen.add_word(0); // 20
gen.add_word(0); // 24
gen.add_word(0); // 28
gen.link_word_to_byte(gen.add_word(0), ambient_arr_slot);
return result;
}
+17
View File
@@ -0,0 +1,17 @@
#pragma once
#include <string>
#include "goalc/build_level/Entity.h"
class DataObjectGenerator;
struct DrawableAmbient {
EntityAmbient ambient;
};
struct DrawableTreeAmbient {
size_t add_to_object_file(DataObjectGenerator& gen,
size_t ambient_count,
size_t ambient_arr_slot) const;
};