Merge branch 'brushbsp' of https://github.com/ericwa/ericw-tools into brushbsp
This commit is contained in:
commit
b3f4bad84a
|
|
@ -641,32 +641,6 @@ static void FloodAreas_r(node_t *node)
|
|||
}
|
||||
}
|
||||
|
||||
static void FloodNode(node_t *node)
|
||||
{
|
||||
if (node->area)
|
||||
return;
|
||||
|
||||
// area portals are always only flooded into, never
|
||||
// out of
|
||||
if (ClusterContents(node).native & Q2_CONTENTS_AREAPORTAL)
|
||||
return;
|
||||
|
||||
map.c_areas++;
|
||||
FloodAreas_r(node);
|
||||
}
|
||||
|
||||
static void FloodNodes_R(node_t *node)
|
||||
{
|
||||
if (!node) {
|
||||
return;
|
||||
}
|
||||
|
||||
FloodNode(node);
|
||||
|
||||
FloodNodes_R(node->children[0]);
|
||||
FloodNodes_R(node->children[1]);
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
FindAreas_r
|
||||
|
|
@ -675,19 +649,30 @@ Just decend the tree, and for each node that hasn't had an
|
|||
area set, flood fill out from there
|
||||
=============
|
||||
*/
|
||||
static void FindAreas(node_t *node)
|
||||
static void FindAreas_r(node_t *node)
|
||||
{
|
||||
auto leaves = FindOccupiedClusters(node);
|
||||
|
||||
if (leaves.empty()) {
|
||||
// map leaked, just flood entire map
|
||||
FloodNodes_R(node);
|
||||
if (!node->is_leaf) {
|
||||
FindAreas_r(node->children[0]);
|
||||
FindAreas_r(node->children[1]);
|
||||
return;
|
||||
}
|
||||
|
||||
if (node->area)
|
||||
return; // already got it
|
||||
|
||||
for (auto *leaf : leaves) {
|
||||
FloodNode(leaf);
|
||||
}
|
||||
if (node->contents.is_any_solid(qbsp_options.target_game))
|
||||
return;
|
||||
|
||||
if (!node->occupied)
|
||||
return; // not reachable from an entity
|
||||
|
||||
// area portals are always only flooded into, never
|
||||
// out of
|
||||
if (node->contents.native & Q2_CONTENTS_AREAPORTAL)
|
||||
return;
|
||||
|
||||
map.c_areas++;
|
||||
FloodAreas_r(node);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -740,7 +725,7 @@ void EmitAreaPortals(node_t *headnode)
|
|||
{
|
||||
logging::funcheader();
|
||||
|
||||
FindAreas(headnode);
|
||||
FindAreas_r(headnode);
|
||||
SetAreaPortalAreas_r(headnode);
|
||||
|
||||
map.bsp.dareaportals.emplace_back();
|
||||
|
|
|
|||
|
|
@ -0,0 +1,88 @@
|
|||
// Game: Quake 2
|
||||
// Format: Quake2
|
||||
// entity 0
|
||||
{
|
||||
"classname" "worldspawn"
|
||||
"_tb_textures" "textures/e1u1"
|
||||
// brush 0
|
||||
{
|
||||
( 48 64 112 ) ( 48 -64 112 ) ( 48 64 -16 ) e1u1/skip 0 0 0 1 1 0 128 0
|
||||
( 64 -64 -16 ) ( 48 -64 -16 ) ( 64 -64 112 ) e1u1/skip 0 0 0 1 1 0 128 0
|
||||
( 64 64 -16 ) ( 48 64 -16 ) ( 64 -64 -16 ) e1u1/skip 0 0 0 1 1 0 128 0
|
||||
( 64 -64 112 ) ( 48 -64 112 ) ( 64 64 112 ) e1u1/skip 0 0 0 1 1 0 128 0
|
||||
( 64 64 112 ) ( 48 64 112 ) ( 64 64 -16 ) e1u1/skip 0 0 0 1 1 0 128 0
|
||||
( 64 -64 112 ) ( 64 64 112 ) ( 64 -64 -16 ) e1u1/skip 0 0 0 1 1 0 128 0
|
||||
}
|
||||
// brush 1
|
||||
{
|
||||
( -64 -64 -16 ) ( -64 64 -16 ) ( -64 -64 112 ) e1u1/skip 0 0 0 1 1 0 128 0
|
||||
( -64 -64 112 ) ( -48 -64 112 ) ( -64 -64 -16 ) e1u1/skip 0 0 0 1 1 0 128 0
|
||||
( -64 -64 -16 ) ( -48 -64 -16 ) ( -64 64 -16 ) e1u1/skip 0 0 0 1 1 0 128 0
|
||||
( -64 64 112 ) ( -48 64 112 ) ( -64 -64 112 ) e1u1/skip 0 0 0 1 1 0 128 0
|
||||
( -64 64 -16 ) ( -48 64 -16 ) ( -64 64 112 ) e1u1/skip 0 0 0 1 1 0 128 0
|
||||
( -48 -64 -16 ) ( -48 -64 112 ) ( -48 64 -16 ) e1u1/skip 0 0 0 1 1 0 128 0
|
||||
}
|
||||
// brush 2
|
||||
{
|
||||
( -48 64 112 ) ( -48 48 112 ) ( -48 64 -16 ) e1u1/skip 0 0 0 1 1 0 128 0
|
||||
( 48 48 112 ) ( 48 48 -16 ) ( -48 48 112 ) e1u1/skip 0 0 0 1 1 0 128 0
|
||||
( -48 64 -16 ) ( -48 48 -16 ) ( 48 64 -16 ) e1u1/skip 0 0 0 1 1 0 128 0
|
||||
( 48 64 112 ) ( 48 48 112 ) ( -48 64 112 ) e1u1/skip 0 0 0 1 1 0 128 0
|
||||
( 48 64 112 ) ( -48 64 112 ) ( 48 64 -16 ) e1u1/skip 0 0 0 1 1 0 128 0
|
||||
( 48 64 -16 ) ( 48 48 -16 ) ( 48 64 112 ) e1u1/skip 0 0 0 1 1 0 128 0
|
||||
}
|
||||
// brush 3
|
||||
{
|
||||
( -48 -64 -16 ) ( -48 -48 -16 ) ( -48 -64 112 ) e1u1/skip 0 0 0 1 1 0 128 0
|
||||
( 48 -64 -16 ) ( -48 -64 -16 ) ( 48 -64 112 ) e1u1/skip 0 0 0 1 1 0 128 0
|
||||
( 48 -64 -16 ) ( 48 -48 -16 ) ( -48 -64 -16 ) e1u1/skip 0 0 0 1 1 0 128 0
|
||||
( -48 -64 112 ) ( -48 -48 112 ) ( 48 -64 112 ) e1u1/skip 0 0 0 1 1 0 128 0
|
||||
( -48 -48 -16 ) ( 48 -48 -16 ) ( -48 -48 112 ) e1u1/skip 0 0 0 1 1 0 128 0
|
||||
( 48 -64 112 ) ( 48 -48 112 ) ( 48 -64 -16 ) e1u1/skip 0 0 0 1 1 0 128 0
|
||||
}
|
||||
// brush 4
|
||||
{
|
||||
( -48 -48 112 ) ( -48 -48 96 ) ( -48 48 112 ) e1u1/skip 0 0 0 1 1 0 128 0
|
||||
( 48 -48 112 ) ( 48 -48 96 ) ( -48 -48 112 ) e1u1/skip 0 0 0 1 1 0 128 0
|
||||
( 48 48 96 ) ( -48 48 96 ) ( 48 -48 96 ) e1u1/skip 0 0 0 1 1 0 128 0
|
||||
( 48 48 112 ) ( 48 -48 112 ) ( -48 48 112 ) e1u1/skip 0 0 0 1 1 0 128 0
|
||||
( -48 48 112 ) ( -48 48 96 ) ( 48 48 112 ) e1u1/skip 0 0 0 1 1 0 128 0
|
||||
( 48 48 112 ) ( 48 48 96 ) ( 48 -48 112 ) e1u1/skip 0 0 0 1 1 0 128 0
|
||||
}
|
||||
// brush 5
|
||||
{
|
||||
( -48 48 -16 ) ( -48 48 0 ) ( -48 -48 -16 ) e1u1/skip 0 0 0 1 1 0 128 0
|
||||
( -48 -48 -16 ) ( -48 -48 0 ) ( 48 -48 -16 ) e1u1/skip 0 0 0 1 1 0 128 0
|
||||
( -48 48 -16 ) ( -48 -48 -16 ) ( 48 48 -16 ) e1u1/skip 0 0 0 1 1 0 128 0
|
||||
( -48 -48 0 ) ( -48 48 0 ) ( 48 -48 0 ) e1u1/skip 0 0 0 1 1 0 128 0
|
||||
( 48 48 -16 ) ( 48 48 0 ) ( -48 48 -16 ) e1u1/skip 0 0 0 1 1 0 128 0
|
||||
( 48 -48 -16 ) ( 48 -48 0 ) ( 48 48 -16 ) e1u1/skip 0 0 0 1 1 0 128 0
|
||||
}
|
||||
// brush 6
|
||||
{
|
||||
( -48 0 80 ) ( -48 1 80 ) ( -48 0 81 ) e1u1/skip 0 16 0 1 1
|
||||
( -48 -48 80 ) ( -48 -48 81 ) ( -47 -48 80 ) e1u1/skip 0 16 0 1 1
|
||||
( -48 0 80 ) ( -47 0 80 ) ( -48 1 80 ) e1u1/box3_4 0 0 0 1 1
|
||||
( 48 16 96 ) ( 48 17 96 ) ( 49 16 96 ) e1u1/skip 0 0 0 1 1
|
||||
( 48 48 96 ) ( 49 48 96 ) ( 48 48 97 ) e1u1/skip 0 16 0 1 1
|
||||
( 48 16 96 ) ( 48 16 97 ) ( 48 17 96 ) e1u1/skip 0 16 0 1 1
|
||||
}
|
||||
}
|
||||
// entity 1
|
||||
{
|
||||
"classname" "func_areaportal"
|
||||
// brush 0
|
||||
{
|
||||
( -48 0 0 ) ( -48 1 0 ) ( -48 0 1 ) e1u1/trigger 0 0 0 1 1
|
||||
( -16 0 0 ) ( -16 0 1 ) ( -15 0 0 ) e1u1/trigger 0 0 0 1 1
|
||||
( -16 0 0 ) ( -15 0 0 ) ( -16 1 0 ) e1u1/trigger 0 0 0 1 1
|
||||
( 48 16 80 ) ( 48 17 80 ) ( 49 16 80 ) e1u1/trigger 0 0 0 1 1
|
||||
( 48 16 16 ) ( 49 16 16 ) ( 48 16 17 ) e1u1/trigger 0 0 0 1 1
|
||||
( 48 16 16 ) ( 48 16 17 ) ( 48 17 16 ) e1u1/trigger 0 0 0 1 1
|
||||
}
|
||||
}
|
||||
// entity 2
|
||||
{
|
||||
"classname" "info_player_start"
|
||||
"origin" "16 -32 24"
|
||||
}
|
||||
|
|
@ -0,0 +1,117 @@
|
|||
// Game: Quake 2
|
||||
// Format: Quake2
|
||||
// entity 0
|
||||
{
|
||||
"classname" "worldspawn"
|
||||
"_tb_textures" "textures/e1u1"
|
||||
// brush 0
|
||||
{
|
||||
( 60 128 112 ) ( 60 -128 112 ) ( 60 128 -16 ) e1u1/c_met11_2 0 0 0 1 1
|
||||
( 64 -128 -16 ) ( 60 -128 -16 ) ( 64 -128 112 ) e1u1/c_met11_2 0 0 0 1 1
|
||||
( 64 128 -16 ) ( 60 128 -16 ) ( 64 -128 -16 ) e1u1/c_met11_2 0 0 0 1 1
|
||||
( 64 -128 112 ) ( 60 -128 112 ) ( 64 128 112 ) e1u1/c_met11_2 0 0 0 1 1
|
||||
( 64 128 112 ) ( 60 128 112 ) ( 64 128 -16 ) e1u1/c_met11_2 0 0 0 1 1
|
||||
( 64 -128 112 ) ( 64 128 112 ) ( 64 -128 -16 ) e1u1/c_met11_2 0 0 0 1 1
|
||||
}
|
||||
// brush 1
|
||||
{
|
||||
( -64 -128 -16 ) ( -64 128 -16 ) ( -64 -128 112 ) e1u1/c_met11_2 0 0 0 1 1
|
||||
( -64 -128 112 ) ( -60 -128 112 ) ( -64 -128 -16 ) e1u1/c_met11_2 0 0 0 1 1
|
||||
( -64 -128 -16 ) ( -60 -128 -16 ) ( -64 128 -16 ) e1u1/c_met11_2 0 0 0 1 1
|
||||
( -64 128 112 ) ( -60 128 112 ) ( -64 -128 112 ) e1u1/c_met11_2 0 0 0 1 1
|
||||
( -64 128 -16 ) ( -60 128 -16 ) ( -64 128 112 ) e1u1/c_met11_2 0 0 0 1 1
|
||||
( -60 -128 -16 ) ( -60 -128 112 ) ( -60 128 -16 ) e1u1/c_met11_2 0 0 0 1 1
|
||||
}
|
||||
// brush 2
|
||||
{
|
||||
( -60 128 112 ) ( -60 124 112 ) ( -60 128 -16 ) e1u1/c_met11_2 0 0 0 1 1
|
||||
( 60 124 112 ) ( 60 124 -16 ) ( -60 124 112 ) e1u1/c_met11_2 0 0 0 1 1
|
||||
( -60 128 -16 ) ( -60 124 -16 ) ( 60 128 -16 ) e1u1/c_met11_2 0 0 0 1 1
|
||||
( 60 128 112 ) ( 60 124 112 ) ( -60 128 112 ) e1u1/c_met11_2 0 0 0 1 1
|
||||
( 60 128 112 ) ( -60 128 112 ) ( 60 128 -16 ) e1u1/c_met11_2 0 0 0 1 1
|
||||
( 60 128 -16 ) ( 60 124 -16 ) ( 60 128 112 ) e1u1/c_met11_2 0 0 0 1 1
|
||||
}
|
||||
// brush 3
|
||||
{
|
||||
( -60 -128 -16 ) ( -60 -124 -16 ) ( -60 -128 112 ) e1u1/c_met11_2 0 0 0 1 1
|
||||
( 60 -128 -16 ) ( -60 -128 -16 ) ( 60 -128 112 ) e1u1/c_met11_2 0 0 0 1 1
|
||||
( 60 -128 -16 ) ( 60 -124 -16 ) ( -60 -128 -16 ) e1u1/c_met11_2 0 0 0 1 1
|
||||
( -60 -128 112 ) ( -60 -124 112 ) ( 60 -128 112 ) e1u1/c_met11_2 0 0 0 1 1
|
||||
( -60 -124 -16 ) ( 60 -124 -16 ) ( -60 -124 112 ) e1u1/c_met11_2 0 0 0 1 1
|
||||
( 60 -128 112 ) ( 60 -124 112 ) ( 60 -128 -16 ) e1u1/c_met11_2 0 0 0 1 1
|
||||
}
|
||||
// brush 4
|
||||
{
|
||||
( -60 -124 112 ) ( -60 -124 108 ) ( -60 124 112 ) e1u1/c_met11_2 0 0 0 1 1
|
||||
( 60 -124 112 ) ( 60 -124 108 ) ( -60 -124 112 ) e1u1/c_met11_2 0 0 0 1 1
|
||||
( 60 124 108 ) ( -60 124 108 ) ( 60 -124 108 ) e1u1/c_met11_2 0 0 0 1 1
|
||||
( 60 124 112 ) ( 60 -124 112 ) ( -60 124 112 ) e1u1/c_met11_2 0 0 0 1 1
|
||||
( -60 124 112 ) ( -60 124 108 ) ( 60 124 112 ) e1u1/c_met11_2 0 0 0 1 1
|
||||
( 60 124 112 ) ( 60 124 108 ) ( 60 -124 112 ) e1u1/c_met11_2 0 0 0 1 1
|
||||
}
|
||||
// brush 5
|
||||
{
|
||||
( -60 124 -16 ) ( -60 124 -12 ) ( -60 -124 -16 ) e1u1/c_met11_2 0 0 0 1 1
|
||||
( -60 -124 -16 ) ( -60 -124 -12 ) ( 60 -124 -16 ) e1u1/c_met11_2 0 0 0 1 1
|
||||
( -60 124 -16 ) ( -60 -124 -16 ) ( 60 124 -16 ) e1u1/c_met11_2 0 0 0 1 1
|
||||
( -60 -124 -12 ) ( -60 124 -12 ) ( 60 -124 -12 ) e1u1/c_met11_2 0 0 0 1 1
|
||||
( 60 124 -16 ) ( 60 124 -12 ) ( -60 124 -16 ) e1u1/c_met11_2 0 0 0 1 1
|
||||
( 60 -124 -16 ) ( 60 -124 -12 ) ( 60 124 -16 ) e1u1/c_met11_2 0 0 0 1 1
|
||||
}
|
||||
// brush 6
|
||||
{
|
||||
( 0 48 -12 ) ( 0 49 -12 ) ( 0 48 -11 ) e1u1/c_met11_2 0 0 0 1 1
|
||||
( 52 32 -12 ) ( 52 32 -11 ) ( 53 32 -12 ) e1u1/c_met11_2 0 0 0 1 1
|
||||
( 52 48 -12 ) ( 53 48 -12 ) ( 52 49 -12 ) e1u1/c_met11_2 0 0 0 1 1
|
||||
( 60 56 108 ) ( 60 57 108 ) ( 61 56 108 ) e1u1/c_met11_2 0 0 0 1 1
|
||||
( 60 56 -8 ) ( 61 56 -8 ) ( 60 56 -7 ) e1u1/c_met11_2 0 0 0 1 1
|
||||
( 60 56 -8 ) ( 60 56 -7 ) ( 60 57 -8 ) e1u1/c_met11_2 0 0 0 1 1
|
||||
}
|
||||
}
|
||||
// entity 1
|
||||
{
|
||||
"classname" "info_player_start"
|
||||
"origin" "-4 -88 12"
|
||||
}
|
||||
// entity 2
|
||||
{
|
||||
"classname" "func_areaportal"
|
||||
"targetname" "a1"
|
||||
// brush 0
|
||||
{
|
||||
( -60 48 -12 ) ( -60 49 -12 ) ( -60 48 -11 ) e1u1/trigger 4 0 0 1 1
|
||||
( -60 48 -12 ) ( -60 48 -11 ) ( -59 48 -12 ) e1u1/trigger 0 0 0 1 1
|
||||
( -60 48 -12 ) ( -59 48 -12 ) ( -60 49 -12 ) e1u1/trigger 0 -4 0 1 1
|
||||
( 0 52 108 ) ( 0 53 108 ) ( 1 52 108 ) e1u1/trigger 0 -4 0 1 1
|
||||
( 0 52 -8 ) ( 1 52 -8 ) ( 0 52 -7 ) e1u1/trigger 0 0 0 1 1
|
||||
( 0 52 -8 ) ( 0 52 -7 ) ( 0 53 -8 ) e1u1/trigger 4 0 0 1 1
|
||||
}
|
||||
}
|
||||
// entity 3
|
||||
{
|
||||
"classname" "func_areaportal"
|
||||
"targetname" "a1"
|
||||
// brush 0
|
||||
{
|
||||
( -60 36 -12 ) ( -60 37 -12 ) ( -60 36 -11 ) e1u1/trigger 16 0 0 1 1
|
||||
( -60 36 -12 ) ( -60 36 -11 ) ( -59 36 -12 ) e1u1/trigger 0 0 0 1 1
|
||||
( -60 36 -12 ) ( -59 36 -12 ) ( -60 37 -12 ) e1u1/trigger 0 -16 0 1 1
|
||||
( 0 40 108 ) ( 0 41 108 ) ( 1 40 108 ) e1u1/trigger 0 -16 0 1 1
|
||||
( 0 40 -8 ) ( 1 40 -8 ) ( 0 40 -7 ) e1u1/trigger 0 0 0 1 1
|
||||
( 0 40 -8 ) ( 0 40 -7 ) ( 0 41 -8 ) e1u1/trigger 16 0 0 1 1
|
||||
}
|
||||
}
|
||||
// entity 4
|
||||
{
|
||||
"classname" "func_door"
|
||||
"target" "a1"
|
||||
// brush 0
|
||||
{
|
||||
( -60 32 -12 ) ( -60 33 -12 ) ( -60 32 -11 ) e1u1/grndoor1 0 0 0 1 1
|
||||
( -60 32 -12 ) ( -60 32 -11 ) ( -59 32 -12 ) e1u1/grndoor1 0 0 0 1 1
|
||||
( -60 32 -12 ) ( -59 32 -12 ) ( -60 33 -12 ) e1u1/grndoor1 0 0 0 1 1
|
||||
( 0 48 108 ) ( 0 49 108 ) ( 1 48 108 ) e1u1/grndoor1 0 0 0 1 1
|
||||
( 0 56 -8 ) ( 1 56 -8 ) ( 0 56 -7 ) e1u1/grndoor1 0 0 0 1 1
|
||||
( 0 48 -8 ) ( 0 48 -7 ) ( 0 49 -8 ) e1u1/grndoor1 0 0 0 1 1
|
||||
}
|
||||
}
|
||||
|
|
@ -1740,6 +1740,34 @@ TEST_CASE("qbsp_q2_detail_seals", "[testmaps_q2]") {
|
|||
CHECK(Q2_CONTENTS_SOLID == BSP_FindLeafAtPoint(&bsp, &bsp.dmodels[0], in_void)->contents);
|
||||
}
|
||||
|
||||
/**
|
||||
* Two areaportals with a small gap in between creating another area.
|
||||
*
|
||||
* Also, the faces on the ceiling/floor cross the areaportal
|
||||
* (due to our aggressive face merging).
|
||||
*/
|
||||
TEST_CASE("q2_double_areaportal", "[testmaps_q2]")
|
||||
{
|
||||
const auto [bsp, bspx, prt] = LoadTestmapQ2("q2_double_areaportal.map");
|
||||
|
||||
CHECK(GAME_QUAKE_II == bsp.loadversion->game->id);
|
||||
CheckFilled(bsp);
|
||||
|
||||
CHECK(4 == bsp.dareas.size());
|
||||
CHECK(5 == bsp.dareaportals.size());
|
||||
}
|
||||
|
||||
TEST_CASE("q2_areaportal_split", "[testmaps_q2]")
|
||||
{
|
||||
const auto [bsp, bspx, prt] = LoadTestmapQ2("q2_areaportal_split.map");
|
||||
|
||||
CHECK(GAME_QUAKE_II == bsp.loadversion->game->id);
|
||||
CheckFilled(bsp);
|
||||
|
||||
CHECK(3 == bsp.dareas.size()); // 1 invalid index zero reserved + 2 areas
|
||||
CHECK(2 == bsp.dareaportals.size()); // 1 invalid index zero reserved + 1 portal
|
||||
}
|
||||
|
||||
/**
|
||||
* Q1 sealing test:
|
||||
* - hull0 can use Q2 method (fill inside)
|
||||
|
|
|
|||
Loading…
Reference in New Issue