build: use jsoncpp instead of nlohmann

bspinfo.cc build time reduced from 2.6s to 1.9s
This commit is contained in:
Eric Wasylishen 2023-09-18 21:26:20 -06:00
parent 64826f414d
commit 83fda6d3a0
12 changed files with 302 additions and 250 deletions

3
.gitmodules vendored
View File

@ -1,9 +1,6 @@
[submodule "lib/fmt"]
path = 3rdparty/fmt
url = https://github.com/fmtlib/fmt
[submodule "3rdparty/json"]
path = 3rdparty/json
url = https://github.com/ArthurSonzogni/nlohmann_json_cmake_fetchcontent
[submodule "3rdparty/nanobench"]
path = 3rdparty/nanobench
url = https://github.com/martinus/nanobench

View File

@ -1,6 +1,5 @@
add_subdirectory(fmt EXCLUDE_FROM_ALL)
add_subdirectory(doctest EXCLUDE_FROM_ALL)
add_subdirectory(json EXCLUDE_FROM_ALL)
add_subdirectory(nanobench EXCLUDE_FROM_ALL)
set(BUILD_WITH_PEDANTIC_WARNINGS OFF CACHE BOOL "prevent pareto from adding /WX" FORCE)

1
3rdparty/json vendored

@ -1 +0,0 @@
Subproject commit 0db99d5ed1ba0c4409509db3916e7bd8398ee920

View File

@ -54,7 +54,9 @@ add_library(common STATIC
../include/common/mapfile.hh
)
target_link_libraries(common ${CMAKE_THREAD_LIBS_INIT} TBB::tbb TBB::tbbmalloc fmt::fmt nlohmann_json::nlohmann_json pareto)
find_package(jsoncpp CONFIG REQUIRED)
target_link_libraries(common ${CMAKE_THREAD_LIBS_INIT} TBB::tbb TBB::tbbmalloc fmt::fmt JsonCpp::JsonCpp pareto)
target_precompile_headers(common INTERFACE
<filesystem>

View File

@ -49,9 +49,9 @@ static std::string hex_string(const uint8_t *bytes, const size_t count)
/**
* returns a JSON array of models
*/
static json serialize_bspxbrushlist(const std::vector<uint8_t> &lump)
static Json::Value serialize_bspxbrushlist(const std::vector<uint8_t> &lump)
{
json j = json::array();
Json::Value j = Json::Value(Json::arrayValue);
imemstream p(lump.data(), lump.size(), std::ios_base::in | std::ios_base::binary);
@ -60,24 +60,24 @@ static json serialize_bspxbrushlist(const std::vector<uint8_t> &lump)
p >= structured;
for (const bspxbrushes_permodel &src_model : structured.models) {
json &model = j.insert(j.end(), json::object()).value();
auto &model = j.append(Json::Value(Json::objectValue));
model["ver"] = src_model.ver;
model["modelnum"] = src_model.modelnum;
model["numbrushes"] = src_model.brushes.size();
model["numfaces"] = src_model.numfaces;
json &brushes = (model.emplace("brushes", json::array())).first.value();
auto &brushes = (model["brushes"] = Json::Value(Json::arrayValue));
for (const bspxbrushes_perbrush &src_brush : src_model.brushes) {
json &brush = brushes.insert(brushes.end(), json::object()).value();
brush.push_back({"mins", src_brush.bounds.mins()});
brush.push_back({"maxs", src_brush.bounds.maxs()});
brush.push_back({"contents", src_brush.contents});
json &faces = (brush.emplace("faces", json::array())).first.value();
auto &brush = brushes.append(Json::Value(Json::objectValue));
brush["mins"] = to_json(src_brush.bounds.mins());
brush["maxs"] = to_json(src_brush.bounds.maxs());
brush["contents"] = src_brush.contents;
auto &faces = (brush["faces"] = Json::Value(Json::arrayValue));
for (const bspxbrushes_perface &src_face : src_brush.faces) {
json &face = faces.insert(faces.end(), json::object()).value();
face.push_back({"normal", src_face.normal});
face.push_back({"dist", src_face.dist});
auto &face = faces.append(Json::Value(Json::objectValue));
face["normal"] = to_json(src_face.normal);
face["dist"] = src_face.dist;
}
}
}
@ -85,9 +85,9 @@ static json serialize_bspxbrushlist(const std::vector<uint8_t> &lump)
return j;
}
static json serialize_bspx_decoupled_lm(const std::vector<uint8_t> &lump)
static Json::Value serialize_bspx_decoupled_lm(const std::vector<uint8_t> &lump)
{
json j = json::array();
auto j = Json::Value(Json::arrayValue);
imemstream p(lump.data(), lump.size(), std::ios_base::in | std::ios_base::binary);
@ -101,12 +101,14 @@ static json serialize_bspx_decoupled_lm(const std::vector<uint8_t> &lump)
break;
}
json &model = j.insert(j.end(), json::object()).value();
auto &model = j.append(Json::objectValue);
model["lmwidth"] = src_face.lmwidth;
model["lmheight"] = src_face.lmheight;
model["offset"] = src_face.offset;
model["world_to_lm_space"] =
json::array({src_face.world_to_lm_space.row(0), src_face.world_to_lm_space.row(1)});
model["world_to_lm_space"] = json_array({
to_json(src_face.world_to_lm_space.row(0)),
to_json(src_face.world_to_lm_space.row(1))
});
}
return j;
@ -548,35 +550,36 @@ static void export_obj_and_lightmaps(const mbsp_t &bsp, const bspxentries_t &bsp
void serialize_bsp(const bspdata_t &bspdata, const mbsp_t &bsp, const fs::path &name)
{
json j = json::object();
auto j = Json::Value(Json::objectValue);
if (!bsp.dmodels.empty()) {
json &models = (j.emplace("models", json::array())).first.value();
auto &models = (j["models"] = Json::Value(Json::arrayValue));
for (auto &src_model : bsp.dmodels) {
json &model = models.insert(models.end(), json::object()).value();
auto &model = models.append(Json::Value(Json::objectValue));
model.push_back({"mins", src_model.mins});
model.push_back({"maxs", src_model.maxs});
model.push_back({"origin", src_model.origin});
model.push_back({"headnode", src_model.headnode});
model.push_back({"visleafs", src_model.visleafs});
model.push_back({"firstface", src_model.firstface});
model.push_back({"numfaces", src_model.numfaces});
model["mins"] = to_json(src_model.mins);
model["maxs"] = to_json(src_model.maxs);
model["origin"] = to_json(src_model.origin);
model["headnode"] = to_json(src_model.headnode);
model["visleafs"] = src_model.visleafs;
model["firstface"] = src_model.firstface;
model["numfaces"] = src_model.numfaces;
}
}
if (bsp.dvis.bits.size()) {
if (bsp.dvis.bit_offsets.size()) {
json &visdata = (j.emplace("visdata", json::object())).first.value();
auto &visdata = j["visdata"];
visdata = Json::Value(Json::objectValue);
json &pvs = (visdata.emplace("pvs", json::array())).first.value();
json &phs = (visdata.emplace("pvs", json::array())).first.value();
auto &pvs = (visdata["pvs"] = Json::Value(Json::arrayValue));
auto &phs = (visdata["pvs"] = Json::Value(Json::arrayValue));
for (auto &offset : bsp.dvis.bit_offsets) {
pvs.push_back(offset[VIS_PVS]);
phs.push_back(offset[VIS_PHS]);
pvs.append(offset[VIS_PVS]);
phs.append(offset[VIS_PHS]);
}
visdata["bits"] = hex_string(bsp.dvis.bits.data(), bsp.dvis.bits.size());
@ -594,207 +597,207 @@ void serialize_bsp(const bspdata_t &bspdata, const mbsp_t &bsp, const fs::path &
}
if (!bsp.dleafs.empty()) {
json &leafs = (j.emplace("leafs", json::array())).first.value();
auto &leafs = (j["leafs"] = Json::Value(Json::arrayValue));
for (auto &src_leaf : bsp.dleafs) {
json &leaf = leafs.insert(leafs.end(), json::object()).value();
auto &leaf = leafs.append(Json::Value(Json::objectValue));
leaf.push_back({"contents", src_leaf.contents});
leaf.push_back({"visofs", src_leaf.visofs});
leaf.push_back({"mins", src_leaf.mins});
leaf.push_back({"maxs", src_leaf.maxs});
leaf.push_back({"firstmarksurface", src_leaf.firstmarksurface});
leaf.push_back({"nummarksurfaces", src_leaf.nummarksurfaces});
leaf.push_back({"ambient_level", src_leaf.ambient_level});
leaf.push_back({"cluster", src_leaf.cluster});
leaf.push_back({"area", src_leaf.area});
leaf.push_back({"firstleafbrush", src_leaf.firstleafbrush});
leaf.push_back({"numleafbrushes", src_leaf.numleafbrushes});
leaf["contents"] = src_leaf.contents;
leaf["visofs"] = src_leaf.visofs;
leaf["mins"] = to_json(src_leaf.mins);
leaf["maxs"] = to_json(src_leaf.maxs);
leaf["firstmarksurface"] = src_leaf.firstmarksurface;
leaf["nummarksurfaces"] = src_leaf.nummarksurfaces;
leaf["ambient_level"] = to_json(src_leaf.ambient_level);
leaf["cluster"] = src_leaf.cluster;
leaf["area"] = src_leaf.area;
leaf["firstleafbrush"] = src_leaf.firstleafbrush;
leaf["numleafbrushes"] = src_leaf.numleafbrushes;
}
}
if (!bsp.dplanes.empty()) {
json &planes = (j.emplace("planes", json::array())).first.value();
auto &planes = (j["planes"] = Json::Value(Json::arrayValue));
for (auto &src_plane : bsp.dplanes) {
json &plane = planes.insert(planes.end(), json::object()).value();
auto &plane = planes.append(Json::Value(Json::objectValue));
plane.push_back({"normal", src_plane.normal});
plane.push_back({"dist", src_plane.dist});
plane.push_back({"type", src_plane.type});
plane["normal"] = to_json(src_plane.normal);
plane["dist"] = src_plane.dist;
plane["type"] = src_plane.type;
}
}
if (!bsp.dvertexes.empty()) {
json &vertexes = (j.emplace("vertexes", json::array())).first.value();
auto &vertexes = (j["vertexes"] = Json::Value(Json::arrayValue));
for (auto &src_vertex : bsp.dvertexes) {
vertexes.insert(vertexes.end(), src_vertex);
vertexes.append(to_json(src_vertex));
}
}
if (!bsp.dnodes.empty()) {
json &nodes = (j.emplace("nodes", json::array())).first.value();
auto &nodes = (j["nodes"] = Json::Value(Json::arrayValue));
for (auto &src_node : bsp.dnodes) {
json &node = nodes.insert(nodes.end(), json::object()).value();
auto &node = nodes.append(Json::Value(Json::objectValue));
node.push_back({"planenum", src_node.planenum});
node.push_back({"children", src_node.children});
node.push_back({"mins", src_node.mins});
node.push_back({"maxs", src_node.maxs});
node.push_back({"firstface", src_node.firstface});
node.push_back({"numfaces", src_node.numfaces});
node["planenum"] = src_node.planenum;
node["children"] = to_json(src_node.children);
node["mins"] = to_json(src_node.mins);
node["maxs"] = to_json(src_node.maxs);
node["firstface"] = src_node.firstface;
node["numfaces"] = src_node.numfaces;
// human-readable plane
auto &plane = bsp.dplanes.at(src_node.planenum);
node.push_back({"plane", json::array({plane.normal[0], plane.normal[1], plane.normal[2], plane.dist})});
node["plane"] = json_array({plane.normal[0], plane.normal[1], plane.normal[2], plane.dist});
}
}
if (!bsp.texinfo.empty()) {
json &texinfos = (j.emplace("texinfo", json::array())).first.value();
auto &texinfos = (j["texinfo"] = Json::Value(Json::arrayValue));
for (auto &src_texinfo : bsp.texinfo) {
json &texinfo = texinfos.insert(texinfos.end(), json::object()).value();
auto &texinfo = texinfos.append(Json::Value(Json::objectValue));
texinfo.push_back({"vecs", json::array({json::array({src_texinfo.vecs.at(0, 0), src_texinfo.vecs.at(0, 1),
texinfo["vecs"] = json_array({json_array({src_texinfo.vecs.at(0, 0), src_texinfo.vecs.at(0, 1),
src_texinfo.vecs.at(0, 2), src_texinfo.vecs.at(0, 3)}),
json::array({src_texinfo.vecs.at(1, 0), src_texinfo.vecs.at(1, 1),
src_texinfo.vecs.at(1, 2), src_texinfo.vecs.at(1, 3)})})});
texinfo.push_back({"flags", src_texinfo.flags.native});
texinfo.push_back({"miptex", src_texinfo.miptex});
texinfo.push_back({"value", src_texinfo.value});
texinfo.push_back({"texture", std::string(src_texinfo.texture.data())});
texinfo.push_back({"nexttexinfo", src_texinfo.nexttexinfo});
json_array({src_texinfo.vecs.at(1, 0), src_texinfo.vecs.at(1, 1),
src_texinfo.vecs.at(1, 2), src_texinfo.vecs.at(1, 3)})});
texinfo["flags"] = src_texinfo.flags.native;
texinfo["miptex"] = src_texinfo.miptex;
texinfo["value"] = src_texinfo.value;
texinfo["texture"] = std::string(src_texinfo.texture.data());
texinfo["nexttexinfo"] = src_texinfo.nexttexinfo;
}
}
if (!bsp.dfaces.empty()) {
json &faces = (j.emplace("faces", json::array())).first.value();
auto &faces = (j["faces"] = Json::Value(Json::arrayValue));
for (auto &src_face : bsp.dfaces) {
json &face = faces.insert(faces.end(), json::object()).value();
auto &face = faces.append(Json::Value(Json::objectValue));
face.push_back({"planenum", src_face.planenum});
face.push_back({"side", src_face.side});
face.push_back({"firstedge", src_face.firstedge});
face.push_back({"numedges", src_face.numedges});
face.push_back({"texinfo", src_face.texinfo});
face.push_back({"styles", src_face.styles});
face.push_back({"lightofs", src_face.lightofs});
face["planenum"] = src_face.planenum;
face["side"] = src_face.side;
face["firstedge"] = src_face.firstedge;
face["numedges"] = src_face.numedges;
face["texinfo"] = src_face.texinfo;
face["styles"] = to_json(src_face.styles);
face["lightofs"] = src_face.lightofs;
// for readibility, also output the actual vertices
auto verts = json::array();
auto verts = Json::Value(Json::arrayValue);
for (int32_t k = 0; k < src_face.numedges; ++k) {
auto se = bsp.dsurfedges[src_face.firstedge + k];
uint32_t v = (se < 0) ? bsp.dedges[-se][1] : bsp.dedges[se][0];
verts.push_back(bsp.dvertexes[v]);
verts.append(to_json(bsp.dvertexes[v]));
}
face.push_back({"vertices", verts});
face["vertices"] = verts;
#if 0
if (auto lm = get_lightmap_face(bsp, src_face, false)) {
face.push_back({"lightmap", serialize_image(lm)});
face["lightmap", serialize_image(lm)});
}
#endif
}
}
if (!bsp.dclipnodes.empty()) {
json &clipnodes = (j.emplace("clipnodes", json::array())).first.value();
auto &clipnodes = (j["clipnodes"] = Json::Value(Json::arrayValue));
for (auto &src_clipnodes : bsp.dclipnodes) {
json &clipnode = clipnodes.insert(clipnodes.end(), json::object()).value();
auto &clipnode = clipnodes.append(Json::Value(Json::objectValue));
clipnode.push_back({"planenum", src_clipnodes.planenum});
clipnode.push_back({"children", src_clipnodes.children});
clipnode["planenum"] = src_clipnodes.planenum;
clipnode["children"] = to_json(src_clipnodes.children);
}
}
if (!bsp.dedges.empty()) {
json &edges = (j.emplace("edges", json::array())).first.value();
auto &edges = (j["edges"] = Json::Value(Json::arrayValue));
for (auto &src_edge : bsp.dedges) {
edges.insert(edges.end(), src_edge);
edges.append(to_json(src_edge));
}
}
if (!bsp.dleaffaces.empty()) {
json &leaffaces = (j.emplace("leaffaces", json::array())).first.value();
auto &leaffaces = (j["leaffaces"] = Json::Value(Json::arrayValue));
for (auto &src_leafface : bsp.dleaffaces) {
leaffaces.insert(leaffaces.end(), src_leafface);
leaffaces.append(src_leafface);
}
}
if (!bsp.dsurfedges.empty()) {
json &surfedges = (j.emplace("surfedges", json::array())).first.value();
auto &surfedges = (j["surfedges"] = Json::Value(Json::arrayValue));
for (auto &src_surfedges : bsp.dsurfedges) {
surfedges.insert(surfedges.end(), src_surfedges);
surfedges.append(src_surfedges);
}
}
if (!bsp.dbrushsides.empty()) {
json &brushsides = (j.emplace("brushsides", json::array())).first.value();
auto &brushsides = (j["brushsides"] = Json::Value(Json::arrayValue));
for (auto &src_brushside : bsp.dbrushsides) {
json &brushside = brushsides.insert(brushsides.end(), json::object()).value();
auto &brushside = brushsides.append(Json::Value(Json::objectValue));
brushside.push_back({"planenum", src_brushside.planenum});
brushside.push_back({"texinfo", src_brushside.texinfo});
brushside["planenum"] = src_brushside.planenum;
brushside["texinfo"] = src_brushside.texinfo;
}
}
if (!bsp.dbrushes.empty()) {
json &brushes = (j.emplace("brushes", json::array())).first.value();
auto &brushes = (j["brushes"] = Json::Value(Json::arrayValue));
for (auto &src_brush : bsp.dbrushes) {
json &brush = brushes.insert(brushes.end(), json::object()).value();
auto &brush = brushes.append(Json::Value(Json::objectValue));
brush.push_back({"firstside", src_brush.firstside});
brush.push_back({"numsides", src_brush.numsides});
brush.push_back({"contents", src_brush.contents});
brush["firstside"] = src_brush.firstside;
brush["numsides"] = src_brush.numsides;
brush["contents"] = src_brush.contents;
}
}
if (!bsp.dleafbrushes.empty()) {
json &leafbrushes = (j.emplace("leafbrushes", json::array())).first.value();
auto &leafbrushes = (j["leafbrushes"] = Json::Value(Json::arrayValue));
for (auto &src_leafbrush : bsp.dleafbrushes) {
leafbrushes.push_back(src_leafbrush);
leafbrushes.append(src_leafbrush);
}
}
if (bsp.dtex.textures.size()) {
json &textures = (j.emplace("textures", json::array())).first.value();
auto &textures = (j["textures"] = Json::Value(Json::arrayValue));
for (auto &src_tex : bsp.dtex.textures) {
if (src_tex.null_texture) {
// use json null to indicate offset -1
textures.insert(textures.end(), json(nullptr));
textures.append(Json::Value(Json::nullValue));
continue;
}
json &tex = textures.insert(textures.end(), json::object()).value();
auto &tex = textures.append(Json::Value(Json::objectValue));
tex.push_back({"name", src_tex.name});
tex.push_back({"width", src_tex.width});
tex.push_back({"height", src_tex.height});
tex["name"] = src_tex.name;
tex["width"] = src_tex.width;
tex["height"] = src_tex.height;
if (src_tex.data.size() > sizeof(dmiptex_t)) {
json &mips = tex["mips"] = json::array();
mips.emplace_back(
auto &mips = tex["mips"] = Json::Value(Json::arrayValue);
mips.append(
serialize_image(img::load_mip(src_tex.name, src_tex.data, false, bspdata.loadversion->game)));
}
}
}
if (!bspdata.bspx.entries.empty()) {
json &bspxentries = (j.emplace("bspxentries", json::array())).first.value();
auto &bspxentries = (j["bspxentries"] = Json::Value(Json::arrayValue));
for (auto &lump : bspdata.bspx.entries) {
json &entry = bspxentries.insert(bspxentries.end(), json::object()).value();
auto &entry = bspxentries.append(Json::Value(Json::objectValue));
entry["lumpname"] = lump.first;
if (lump.first == "BRUSHLIST") {

View File

@ -372,7 +372,7 @@ std::optional<texture_meta> load_wal_json_meta(
const std::string_view &name, const fs::data &file, const gamedef_t *game)
{
try {
auto json = json::parse(file->begin(), file->end());
auto json = parse_json(file->data(), file->data() + file->size());
texture_meta meta{};
@ -386,71 +386,70 @@ std::optional<texture_meta> load_wal_json_meta(
meta = *wal_meta;
}
if (json.contains("width") && json["width"].is_number_integer()) {
meta.width = json["width"].get<int32_t>();
if (json.isMember("width") && json["width"].isInt()) {
meta.width = json["width"].as<int32_t>();
}
if (json.contains("height") && json["height"].is_number_integer()) {
meta.height = json["height"].get<int32_t>();
if (json.isMember("height") && json["height"].isInt()) {
meta.height = json["height"].as<int32_t>();
}
if (json.contains("value") && json["value"].is_number_integer()) {
meta.value = json["value"].get<int32_t>();
if (json.isMember("value") && json["value"].isInt()) {
meta.value = json["value"].as<int32_t>();
}
if (json.contains("contents")) {
if (json.isMember("contents")) {
auto &contents = json["contents"];
if (contents.is_number_integer()) {
meta.contents_native = contents.get<int32_t>();
} else if (contents.is_string()) {
meta.contents_native =
game->contents_from_string(contents.get<std::string>());
} else if (contents.is_array()) {
if (contents.isInt()) {
meta.contents_native = contents.as<int32_t>();
} else if (contents.isString()) {
meta.contents_native = game->contents_from_string(contents.as<std::string>());
} else if (contents.isArray()) {
int native = 0;
for (auto &content : contents) {
if (content.is_number_integer()) {
native |= content.get<int32_t>();
} else if (content.is_string()) {
native |= game->contents_from_string(content.get<std::string>());
if (content.isInt()) {
native |= content.as<int32_t>();
} else if (content.isString()) {
native |= game->contents_from_string(content.as<std::string>());
}
}
meta.contents_native = native;
}
}
if (json.contains("flags")) {
if (json.isMember("flags")) {
auto &flags = json["flags"];
if (flags.is_number_integer()) {
meta.flags.native = flags.get<int32_t>();
} else if (flags.is_string()) {
meta.flags.native = game->surfflags_from_string(flags.get<std::string>());
} else if (flags.is_array()) {
if (flags.isInt()) {
meta.flags.native = flags.as<int32_t>();
} else if (flags.isString()) {
meta.flags.native = game->surfflags_from_string(flags.as<std::string>());
} else if (flags.isArray()) {
for (auto &flag : flags) {
if (flag.is_number_integer()) {
meta.flags.native |= flag.get<int32_t>();
} else if (flag.is_string()) {
meta.flags.native |= game->surfflags_from_string(flag.get<std::string>());
if (flag.isInt()) {
meta.flags.native |= flag.as<int32_t>();
} else if (flag.isString()) {
meta.flags.native |= game->surfflags_from_string(flag.as<std::string>());
}
}
}
}
if (json.contains("animation") && json["animation"].is_string()) {
meta.animation = json["animation"].get<std::string>();
if (json.isMember("animation") && json["animation"].isString()) {
meta.animation = json["animation"].as<std::string>();
}
if (json.contains("color")) {
if (json.isMember("color")) {
auto &color = json["color"];
qvec3b color_vec = {color.at(0).get<int32_t>(), color.at(1).get<int32_t>(), color.at(2).get<int32_t>()};
qvec3b color_vec = {color[0].as<int32_t>(), color[1].as<int32_t>(), color[2].as<int32_t>()};
meta.color_override = {color_vec};
}
return meta;
} catch (json::exception e) {
} catch (Json::Exception e) {
logging::funcprint("{}, invalid JSON: {}\n", name, e.what());
return std::nullopt;
}

View File

@ -21,25 +21,73 @@
// JSON & formatters for our types
#include <nlohmann/json.hpp>
#include <json/json.h>
#include <common/qvec.hh>
using nlohmann::json;
template<typename T, size_t N>
void to_json(json &j, const qvec<T, N> &p)
Json::Value to_json(const qvec<T, N> &p)
{
j = json::array();
auto j = Json::Value(Json::arrayValue);
for (auto &v : p) {
j.push_back(v);
j.append(v);
}
return j;
}
template<typename T>
Json::Value to_json(const std::vector<T> &vec)
{
auto j = Json::Value(Json::arrayValue);
for (auto &v : vec) {
j.append(v);
}
return j;
}
template<class T, size_t N>
Json::Value to_json(const std::array<T, N> &arr)
{
auto j = Json::Value(Json::arrayValue);
for (auto &v : arr) {
j.append(v);
}
return j;
}
template<class T>
Json::Value json_array(std::initializer_list<T> args)
{
auto j = Json::Value(Json::arrayValue);
for (auto &v : args) {
j.append(v);
}
return j;
}
template<typename T, size_t N>
void from_json(const json &j, qvec<T, N> &p)
qvec<T, N> from_json(const Json::Value &j)
{
for (size_t i = 0; i < N; i++) {
p[i] = j[i].get<T>();
qvec<T, N> p;
for (unsigned int i = 0; i < N; i++) {
p[i] = j[i].as<T>();
}
}
return p;
}
static Json::Value parse_json(const uint8_t *begin, const uint8_t *end)
{
Json::Value result;
Json::CharReaderBuilder rbuilder;
auto reader = std::unique_ptr<Json::CharReader>(rbuilder.newCharReader());
reader->parse(reinterpret_cast<const char*>(begin),
reinterpret_cast<const char*>(end), &result, nullptr);
return result;
}

View File

@ -42,7 +42,10 @@ if (embree_FOUND)
endif(embree_FOUND)
add_library(liblight STATIC ${LIGHT_SOURCES})
target_link_libraries(liblight PRIVATE common ${CMAKE_THREAD_LIBS_INIT} fmt::fmt nlohmann_json::nlohmann_json)
find_package(jsoncpp CONFIG REQUIRED)
target_link_libraries(liblight PRIVATE common ${CMAKE_THREAD_LIBS_INIT} fmt::fmt JsonCpp::JsonCpp)
add_executable(light main.cc)
target_link_libraries(light PRIVATE common liblight)

View File

@ -952,105 +952,104 @@ static void LoadExtendedTexinfoFlags(const fs::path &sourcefilename, const mbsp_
logging::print("Loading extended texinfo flags from {}...\n", filename);
json j;
Json::Value j;
texinfofile >> j;
for (auto it = j.begin(); it != j.end(); ++it) {
size_t index = std::stoull(it.key());
for (auto &key : j.getMemberNames()) {
size_t index = std::stoull(key);
if (index >= bsp->texinfo.size()) {
logging::print("WARNING: Extended texinfo flags in {} does not match bsp, ignoring\n", filename);
memset(extended_texinfo_flags.data(), 0, bsp->texinfo.size() * sizeof(surfflags_t));
return;
}
auto &val = it.value();
auto &val = j[key];
auto &flags = extended_texinfo_flags[index];
if (val.contains("is_nodraw")) {
flags.is_nodraw = val.at("is_nodraw").get<bool>();
if (val.isMember("is_nodraw")) {
flags.is_nodraw = val["is_nodraw"].as<bool>();
}
if (val.contains("is_hint")) {
flags.is_hint = val.at("is_hint").get<bool>();
if (val.isMember("is_hint")) {
flags.is_hint = val["is_hint"].as<bool>();
}
if (val.contains("is_hintskip")) {
flags.is_hintskip = val.at("is_hintskip").get<bool>();
if (val.isMember("is_hintskip")) {
flags.is_hintskip = val["is_hintskip"].as<bool>();
}
if (val.contains("no_dirt")) {
flags.no_dirt = val.at("no_dirt").get<bool>();
if (val.isMember("no_dirt")) {
flags.no_dirt = val["no_dirt"].as<bool>();
}
if (val.contains("no_shadow")) {
flags.no_shadow = val.at("no_shadow").get<bool>();
if (val.isMember("no_shadow")) {
flags.no_shadow = val["no_shadow"].as<bool>();
}
if (val.contains("no_bounce")) {
flags.no_bounce = val.at("no_bounce").get<bool>();
if (val.isMember("no_bounce")) {
flags.no_bounce = val["no_bounce"].as<bool>();
}
if (val.contains("no_minlight")) {
flags.no_minlight = val.at("no_minlight").get<bool>();
if (val.isMember("no_minlight")) {
flags.no_minlight = val["no_minlight"].as<bool>();
}
if (val.contains("no_expand")) {
flags.no_expand = val.at("no_expand").get<bool>();
if (val.isMember("no_expand")) {
flags.no_expand = val["no_expand"].as<bool>();
}
if (val.contains("no_phong")) {
flags.no_expand = val.at("no_phong").get<bool>();
if (val.isMember("no_phong")) {
flags.no_expand = val["no_phong"].as<bool>();
}
if (val.contains("light_ignore")) {
flags.light_ignore = val.at("light_ignore").get<bool>();
if (val.isMember("light_ignore")) {
flags.light_ignore = val["light_ignore"].as<bool>();
}
if (val.contains("surflight_rescale")) {
flags.surflight_rescale = val.at("surflight_rescale").get<bool>();
if (val.isMember("surflight_rescale")) {
flags.surflight_rescale = val["surflight_rescale"].as<bool>();
}
if (val.contains("surflight_style")) {
flags.surflight_style = val.at("surflight_style").get<int32_t>();
if (val.isMember("surflight_style")) {
flags.surflight_style = val["surflight_style"].as<int32_t>();
}
if (val.contains("surflight_targetname")) {
flags.surflight_targetname = val.at("surflight_targetname").get<std::string>();
if (val.isMember("surflight_targetname")) {
flags.surflight_targetname = val["surflight_targetname"].as<std::string>();
}
if (val.contains("surflight_color")) {
flags.surflight_color = val.at("surflight_color").get<qvec3b>();
if (val.isMember("surflight_color")) {
flags.surflight_color = from_json<int, 3>(val["surflight_color"]);
}
if (val.contains("surflight_minlight_scale")) {
flags.surflight_minlight_scale = val.at("surflight_minlight_scale").get<float>();
if (val.isMember("surflight_minlight_scale")) {
flags.surflight_minlight_scale = val["surflight_minlight_scale"].as<float>();
}
if (val.contains("phong_angle")) {
flags.phong_angle = val.at("phong_angle").get<float>();
if (val.isMember("phong_angle")) {
flags.phong_angle = val["phong_angle"].as<float>();
}
if (val.contains("phong_angle_concave")) {
flags.phong_angle_concave = val.at("phong_angle_concave").get<float>();
if (val.isMember("phong_angle_concave")) {
flags.phong_angle_concave = val["phong_angle_concave"].as<float>();
}
if (val.contains("phong_group")) {
flags.phong_group = val.at("phong_group").get<int>();
if (val.isMember("phong_group")) {
flags.phong_group = val["phong_group"].as<int>();
}
if (val.contains("minlight")) {
flags.minlight = val.at("minlight").get<float>();
if (val.isMember("minlight")) {
flags.minlight = val["minlight"].as<float>();
}
if (val.contains("maxlight")) {
flags.maxlight = val.at("maxlight").get<float>();
if (val.isMember("maxlight")) {
flags.maxlight = val["maxlight"].as<float>();
}
if (val.contains("minlight_color")) {
flags.minlight_color = val.at("minlight_color").get<qvec3b>();
if (val.isMember("minlight_color")) {
flags.minlight_color = from_json<int, 3>(val["minlight_color"]);
}
if (val.contains("light_alpha")) {
flags.light_alpha = val.at("light_alpha").get<float>();
if (val.isMember("light_alpha")) {
flags.light_alpha = val["light_alpha"].as<float>();
}
if (val.contains("light_twosided")) {
flags.light_twosided = val.at("light_twosided").get<bool>();
if (val.isMember("light_twosided")) {
flags.light_twosided = val["light_twosided"].as<bool>();
}
if (val.contains("lightcolorscale")) {
flags.lightcolorscale = val.at("lightcolorscale").get<float>();
if (val.isMember("lightcolorscale")) {
flags.lightcolorscale = val["lightcolorscale"].as<float>();
}
if (val.contains("surflight_group")) {
flags.surflight_group = val.at("surflight_group").get<int32_t>();
if (val.isMember("surflight_group")) {
flags.surflight_group = val["surflight_group"].as<int32_t>();
}
if (val.contains("world_units_per_luxel")) {
flags.world_units_per_luxel = val.at("world_units_per_luxel").get<float>();
if (val.isMember("world_units_per_luxel")) {
flags.world_units_per_luxel = val["world_units_per_luxel"].as<float>();
}
if (val.contains("object_channel_mask")) {
flags.object_channel_mask = val.at("object_channel_mask").get<int32_t>();
if (val.isMember("object_channel_mask")) {
flags.object_channel_mask = val["object_channel_mask"].as<int32_t>();
}
if (val.contains("surflight_minlight_scale")) {
flags.surflight_minlight_scale = val.at("surflight_minlight_scale").get<float>();
if (val.isMember("surflight_minlight_scale")) {
flags.surflight_minlight_scale = val["surflight_minlight_scale"].as<float>();
}
}
}

View File

@ -120,20 +120,21 @@ size_t lua_count_array(lua_State *state)
}
// pushes value onto stack
static void json_to_lua(lua_State *state, const json &value)
static void json_to_lua(lua_State *state, const Json::Value &value)
{
switch (value.type()) {
case json::value_t::object: {
case Json::ValueType::objectValue: {
lua_newtable(state);
for (auto it = value.begin(); it != value.end(); ++it) {
lua_pushstring(state, it.key().c_str());
json_to_lua(state, it.value());
for (auto &key : value.getMemberNames()) {
const Json::Value &val = value[key];
lua_pushstring(state, key.c_str());
json_to_lua(state, val);
lua_settable(state, -3);
}
return;
}
case json::value_t::array: {
case Json::ValueType::arrayValue: {
lua_newtable(state);
size_t i = 1;
@ -144,27 +145,27 @@ static void json_to_lua(lua_State *state, const json &value)
}
return;
}
case json::value_t::string: {
lua_pushstring(state, value.get<std::string>().c_str());
case Json::ValueType::stringValue: {
lua_pushstring(state, value.asCString());
return;
}
case json::value_t::number_unsigned: {
lua_pushnumber(state, value.get<uint64_t>());
case Json::ValueType::uintValue: {
lua_pushnumber(state, value.asUInt64());
return;
}
case json::value_t::number_integer: {
lua_pushnumber(state, value.get<int64_t>());
case Json::ValueType::intValue: {
lua_pushnumber(state, value.asInt64());
return;
}
case json::value_t::number_float: {
lua_pushnumber(state, value.get<double>());
case Json::ValueType::realValue: {
lua_pushnumber(state, value.asDouble());
return;
}
case json::value_t::boolean: {
lua_pushboolean(state, value.get<bool>());
case Json::ValueType::booleanValue: {
lua_pushboolean(state, value.asBool());
return;
}
case json::value_t::null: {
case Json::ValueType::nullValue: {
lua_pushnil(state);
return;
}
@ -188,7 +189,7 @@ static int l_load_json(lua_State *state)
try
{
auto json = json::parse(result->begin(), result->end());
auto json = parse_json(result->data(), result->data() + result->size());
json_to_lua(state, json);
}

View File

@ -33,7 +33,10 @@ set(QBSP_SOURCES
${QBSP_INCLUDES})
add_library(libqbsp STATIC ${QBSP_SOURCES})
target_link_libraries(libqbsp common ${CMAKE_THREAD_LIBS_INIT} TBB::tbb TBB::tbbmalloc fmt::fmt nlohmann_json::nlohmann_json pareto)
find_package(jsoncpp CONFIG REQUIRED)
target_link_libraries(libqbsp common ${CMAKE_THREAD_LIBS_INIT} TBB::tbb TBB::tbbmalloc fmt::fmt JsonCpp::JsonCpp pareto)
add_executable(qbsp main.cc)
target_link_libraries(qbsp libqbsp)

View File

@ -32,7 +32,6 @@
#include <fstream>
#include <stdexcept>
using nlohmann::json;
/**
* Returns the output plane number
@ -364,13 +363,13 @@ static void WriteExtendedTexinfoFlags()
std::sort(texinfos_sorted.begin(), texinfos_sorted.end(),
[](const maptexinfo_t &a, const maptexinfo_t &b) { return a.outputnum < b.outputnum; });
json texinfofile = json::object();
auto texinfofile = Json::Value(Json::objectValue);
for (const auto &tx : texinfos_sorted) {
if (!tx.outputnum.has_value() || !tx.flags.needs_write())
continue;
json t = json::object();
auto t = Json::Value(Json::objectValue);
if (tx.flags.is_nodraw) {
t["is_nodraw"] = tx.flags.is_nodraw;
@ -409,7 +408,7 @@ static void WriteExtendedTexinfoFlags()
t["surflight_targetname"] = tx.flags.surflight_targetname.value();
}
if (tx.flags.surflight_color.has_value()) {
t["surflight_color"] = tx.flags.surflight_color.value();
t["surflight_color"] = to_json(tx.flags.surflight_color.value());
}
if (tx.flags.surflight_minlight_scale.has_value()) {
t["surflight_minlight_scale"] = tx.flags.surflight_minlight_scale.value();
@ -430,7 +429,7 @@ static void WriteExtendedTexinfoFlags()
t["maxlight"] = tx.flags.maxlight;
}
if (!qv::emptyExact(tx.flags.minlight_color)) {
t["minlight_color"] = tx.flags.minlight_color;
t["minlight_color"] = to_json(tx.flags.minlight_color);
}
if (tx.flags.light_alpha) {
t["light_alpha"] = *tx.flags.light_alpha;