Skip to content

Commit

Permalink
Merge pull request #10 from khanghugo/info-room
Browse files Browse the repository at this point in the history
Add info_portal and info_leaf
  • Loading branch information
seedee authored Jul 8, 2024
2 parents 07827fc + 372df54 commit 1a2a0ae
Show file tree
Hide file tree
Showing 3 changed files with 162 additions and 3 deletions.
120 changes: 119 additions & 1 deletion src/sdhlt/sdHLVIS/vis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,13 @@
#ifdef SYSTEM_WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
// std:clamp() is at least MVSC 19
#define CLAMP(x, min, max) x <= min ? min : x >= max ? max : x
#endif

#ifdef SYSTEM_POSIX
#include <algorithm>
#define CLAMP(x, min, max) std::clamp(x, min, max)
#endif

#ifdef ZHLT_NETVIS
Expand Down Expand Up @@ -75,6 +78,9 @@ overview_t g_overview[g_overview_max];
int g_overview_count = 0;
leafinfo_t* g_leafinfos = NULL;

const int g_room_max = MAX_MAP_ENTITIES;
room_t g_room[g_room_max];
int g_room_count = 0;

static int totalvis = 0;

Expand Down Expand Up @@ -515,6 +521,35 @@ static void LeafThread(int unused)
#pragma warning(pop)
#endif

// Recursively add `add` to `current` visibility leaf.
std::unordered_map<int, bool> leaf_flow_add_exclude = {};
static void LeafFlowNeighborAddLeaf(const int current, const int add, const int neighbor)
{
auto outbuffer = g_uncompressed + current * g_bitbytes;

outbuffer[add >> 3] |= (1 << (add & 7));
leaf_flow_add_exclude[current] = true;

if (neighbor == 0)
{
return;
}

auto leaf = &g_leafs[current];

for (int i = 0; i < leaf->numportals; i++)
{
auto p = leaf->portals[i];

if (leaf_flow_add_exclude[p->leaf]) {
// Log("leaf %d neighbor %d is excluded\n", current, p->leaf);
continue;
}

LeafFlowNeighborAddLeaf(p->leaf, add, neighbor - 1);
}
}

// =====================================================================================
// LeafFlow
// Builds the entire visibility list for a leaf
Expand Down Expand Up @@ -589,6 +624,7 @@ static void LeafFlow(const int leafnum)
outbuffer[i >> 3] |= (1 << (i & 7));
}
}

numvis = 0;
for (i = 0; i < g_portalleafs; i++)
{
Expand Down Expand Up @@ -807,6 +843,19 @@ static void CalcVis()

CalcPortalVis();

// Add additional leaves to the uncompressed vis.
for (i = 0; i < g_portalleafs; i++)
{
if (!g_leafinfos[i].additional_leaves.empty())
{
for (int leaf : g_leafinfos[i].additional_leaves)
{
LeafFlowNeighborAddLeaf(i, leaf, g_leafinfos[i].neighbor);
leaf_flow_add_exclude.clear();
}
}
}

//
// assemble the leaf vis lists by oring and compressing the portal lists
//
Expand Down Expand Up @@ -948,6 +997,25 @@ static void LoadPortals(char* portal_image)
}
}
}

for (j = 0; j < g_room_count; j++)
{
int d1 = g_room[j].visleafnum - g_leafstarts[i];

if (0 <= d1 && d1 < g_leafcounts[i])
{
for (int k = 0; k < g_portalleafs; k++)
{
int d2 = g_room[j].target_visleafnum - g_leafstarts[k];

if (0 <= d2 && d2 < g_leafcounts[k])
{
g_leafinfos[i].additional_leaves.push_back(k);
g_leafinfos[i].neighbor = g_room[j].neighbor;
}
}
}
}
}
for (i = 0, p = g_portals; i < g_numportals; i++)
{
Expand Down Expand Up @@ -1788,7 +1856,10 @@ int main(const int argc, char** argv)
int i;
for (i = 0; i < g_numentities; i++)
{
if (!strcmp (ValueForKey (&g_entities[i], "classname"), "info_overview_point"))
const char* current_entity_classname = ValueForKey (&g_entities[i], "classname");

if (!strcmp (current_entity_classname, "info_overview_point")
)
{
if (g_overview_count < g_overview_max)
{
Expand All @@ -1800,6 +1871,53 @@ int main(const int argc, char** argv)
g_overview_count++;
}
}

else if (!strcmp (current_entity_classname, "info_portal"))
{
if (g_room_count < g_room_max)
{
vec3_t room_origin;

GetVectorForKey (&g_entities[i], "origin", room_origin);
g_room[g_room_count].visleafnum = VisLeafnumForPoint (room_origin);
g_room[g_room_count].neighbor = CLAMP(IntForKey (&g_entities[i], "neighbor"), 0, MAX_ROOM_NEIGHBOR);

const char* target = ValueForKey (&g_entities[i], "target");

if (strlen(target) == 0)
{
continue;
}

bool has_target = false;

// Find the target entity.
// Rewalk yes, very sad.
for (int j = 0; j < g_numentities; j++)
{
const char* current_entity_classname_nested = ValueForKey (&g_entities[j], "classname");

// Find a `info_leaf` and check if its targetname matches our target
if (!strcmp (current_entity_classname_nested, "info_leaf")
&& !strcmp(ValueForKey (&g_entities[j], "targetname"), target))
{
vec3_t room_target_origin;

GetVectorForKey (&g_entities[j], "origin", room_target_origin);
g_room[g_room_count].target_visleafnum = VisLeafnumForPoint (room_target_origin);

has_target = true;
}
}

if (!has_target)
{
Warning("Entity %d (info_portal) does not have a target leaf.", i);
}

g_room_count++;
}
}
}
}
LoadPortalsByFilename(portalfile);
Expand Down
25 changes: 25 additions & 0 deletions src/sdhlt/sdHLVIS/vis.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@
#include "zones.h"
#include "cmdlinecfg.h"

#include <vector>
#include <unordered_map>

#define DEFAULT_MAXDISTANCE_RANGE 0


Expand Down Expand Up @@ -143,6 +146,25 @@ extern unsigned g_portalleafs;

extern unsigned int g_maxdistance;
//extern bool g_postcompile;

// This allows the current leaf to have portal to selected leaf.
// TODO: vector for target so it can do a lot. Though doing the entity won't be as simple.
// That means we need to parse string and what not.
// For the time being, ONE target is good enough.
#define MAX_ROOM_NEIGHBOR 16
typedef struct
{
int visleafnum;
int target_visleafnum;
// Traversal of neighbors being affected.
int neighbor;
}
room_t;
extern const int g_room_max;
extern room_t g_room[];
extern int g_room_count;
extern std::unordered_map<int, bool> leaf_flow_add_exclude;

typedef struct
{
vec3_t origin;
Expand All @@ -158,6 +180,9 @@ typedef struct
{
bool isoverviewpoint;
bool isskyboxpoint;
// For info_portal
std::vector<int> additional_leaves;
int neighbor;
}
leafinfo_t;
extern leafinfo_t *g_leafinfos;
Expand Down
20 changes: 18 additions & 2 deletions tools/sdhlt.fgd
Original file line number Diff line number Diff line change
Expand Up @@ -77,15 +77,31 @@
// info_overview_point
// It makes all entities visible from this place. This is useful for overview mode (dev_overview 1).
// If "Reversed" is selected, this place will become visible from the entire map. This is useful for large skybox model.
@PointClass color(255 0 0) = info_overview_point : "Disable VIS here for overview"
@PointClass color(255 0 0) = info_overview_point : "Disable VIS here by creating portals to every other leaf. Lag/wallhack warning. If reversed, every other leaf has a portal to this one."
[
reverse(choices) : "Reversed" : "" =
reverse(choices) : "Reversed (3D skybox)" : "" =
[
"": "No"
1: "Yes"
]
]

// info_portal
// TODO: vector for target so it can do a lot. Though doing the entity won't be as simple.
// That means we need to parse string and what not.
// For the time being, ONE target is good enough.
@PointClass color(255 200 200) = info_portal : "Create a portal to the selected info_leaf, from the leaf the info_portal is inside. Forces target leaf to be visible from the current one."
[
target(target_source) : "Name of info_leaf"
neighbor(integer) : "TODO: Layers of neighboring leaves to be affected" : 1
]

// info_leaf
@PointClass color(200 200 255) = info_leaf : "Works with info_portal. Used to select a leaf the info_leaf is inside."
[
targetname(target_destination) : "Name"
]

// info_sunlight
// It generates a fake light_environment which defines sv_skycolor and sv_skyvec in game.
// If you are using multiple light_environments, you will probably need this entity.
Expand Down

0 comments on commit 1a2a0ae

Please sign in to comment.