- pass 'level' as a parameter to AABBTree. Also renamed a few things to make the code easier to read.

This commit is contained in:
Christoph Oelckers 2019-01-06 08:24:04 +01:00
parent a0ce8f2988
commit 3328821a98
5 changed files with 46 additions and 40 deletions

View file

@ -27,14 +27,15 @@
namespace hwrenderer
{
LevelAABBTree::LevelAABBTree()
LevelAABBTree::LevelAABBTree(FLevelLocals *lev)
{
Level = lev;
// Calculate the center of all lines
TArray<FVector2> centroids;
for (unsigned int i = 0; i < level.lines.Size(); i++)
for (unsigned int i = 0; i < Level->lines.Size(); i++)
{
FVector2 v1 = { (float)level.lines[i].v1->fX(), (float)level.lines[i].v1->fY() };
FVector2 v2 = { (float)level.lines[i].v2->fX(), (float)level.lines[i].v2->fY() };
FVector2 v1 = { (float)Level->lines[i].v1->fX(), (float)Level->lines[i].v1->fY() };
FVector2 v2 = { (float)Level->lines[i].v2->fX(), (float)Level->lines[i].v2->fY() };
centroids.Push((v1 + v2) * 0.5f);
}
@ -45,7 +46,7 @@ LevelAABBTree::LevelAABBTree()
int staticroot = nodes.Size() - 1;
dynamicStartNode = nodes.Size();
dynamicStartLine = lines.Size();
dynamicStartLine = treelines.Size();
// Create the dynamic subtree
if (GenerateTree(&centroids[0], true))
@ -64,11 +65,11 @@ LevelAABBTree::LevelAABBTree()
}
// Add the lines referenced by the leaf nodes
lines.Resize(mapLines.Size());
treelines.Resize(mapLines.Size());
for (unsigned int i = 0; i < mapLines.Size(); i++)
{
const auto &line = level.lines[mapLines[i]];
auto &treeline = lines[i];
const auto &line = Level->lines[mapLines[i]];
auto &treeline = treelines[i];
treeline.x = (float)line.v1->fX();
treeline.y = (float)line.v1->fY();
@ -81,11 +82,12 @@ bool LevelAABBTree::GenerateTree(const FVector2 *centroids, bool dynamicsubtree)
{
// Create a list of level lines we want to add:
TArray<int> line_elements;
for (unsigned int i = 0; i < level.lines.Size(); i++)
auto &maplines = Level->lines;
for (unsigned int i = 0; i < maplines.Size(); i++)
{
if (!level.lines[i].backsector)
if (!maplines[i].backsector)
{
bool isPolyLine = level.lines[i].sidedef[0] && (level.lines[i].sidedef[0]->Flags & WALLF_POLYOBJ);
bool isPolyLine = maplines[i].sidedef[0] && (maplines[i].sidedef[0]->Flags & WALLF_POLYOBJ);
if (isPolyLine && dynamicsubtree)
{
line_elements.Push(mapLines.Size());
@ -116,7 +118,7 @@ bool LevelAABBTree::Update()
bool modified = false;
for (unsigned int i = dynamicStartLine; i < mapLines.Size(); i++)
{
const auto &line = level.lines[mapLines[i]];
const auto &line = Level->lines[mapLines[i]];
AABBTreeLine treeline;
treeline.x = (float)line.v1->fX();
@ -124,7 +126,7 @@ bool LevelAABBTree::Update()
treeline.dx = (float)line.v2->fX() - treeline.x;
treeline.dy = (float)line.v2->fY() - treeline.y;
if (memcmp(&lines[i], &treeline, sizeof(AABBTreeLine)))
if (memcmp(&treelines[i], &treeline, sizeof(AABBTreeLine)))
{
TArray<int> path = FindNodePath(i, nodes.Size() - 1);
if (path.Size())
@ -151,7 +153,7 @@ bool LevelAABBTree::Update()
cur.aabb_bottom = MAX(left.aabb_bottom, right.aabb_bottom);
}
lines[i] = treeline;
treelines[i] = treeline;
modified = true;
}
}
@ -163,8 +165,8 @@ TArray<int> LevelAABBTree::FindNodePath(unsigned int line, unsigned int node)
{
const AABBTreeNode &n = nodes[node];
if (n.aabb_left > lines[line].x || n.aabb_right < lines[line].x ||
n.aabb_top > lines[line].y || n.aabb_bottom < lines[line].y)
if (n.aabb_left > treelines[line].x || n.aabb_right < treelines[line].x ||
n.aabb_top > treelines[line].y || n.aabb_bottom < treelines[line].y)
{
return {};
}
@ -273,7 +275,7 @@ double LevelAABBTree::IntersectRayLine(const DVector2 &ray_start, const DVector2
// This algorithm is homemade - I would not be surprised if there's a much faster method out there.
const double epsilon = 0.0000001;
const AABBTreeLine &line = lines[line_index];
const AABBTreeLine &line = treelines[line_index];
DVector2 raynormal = DVector2(raydelta.Y, -raydelta.X);
@ -303,15 +305,16 @@ int LevelAABBTree::GenerateTreeNode(int *lines, int num_lines, const FVector2 *c
// Find bounding box and median of the lines
FVector2 median = FVector2(0.0f, 0.0f);
FVector2 aabb_min, aabb_max;
aabb_min.X = (float)level.lines[mapLines[lines[0]]].v1->fX();
aabb_min.Y = (float)level.lines[mapLines[lines[0]]].v1->fY();
auto &maplines = Level->lines;
aabb_min.X = (float)maplines[mapLines[lines[0]]].v1->fX();
aabb_min.Y = (float)maplines[mapLines[lines[0]]].v1->fY();
aabb_max = aabb_min;
for (int i = 0; i < num_lines; i++)
{
float x1 = (float)level.lines[mapLines[lines[i]]].v1->fX();
float y1 = (float)level.lines[mapLines[lines[i]]].v1->fY();
float x2 = (float)level.lines[mapLines[lines[i]]].v2->fX();
float y2 = (float)level.lines[mapLines[lines[i]]].v2->fY();
float x1 = (float)maplines[mapLines[lines[i]]].v1->fX();
float y1 = (float)maplines[mapLines[lines[i]]].v1->fY();
float x2 = (float)maplines[mapLines[lines[i]]].v2->fX();
float y2 = (float)maplines[mapLines[lines[i]]].v2->fY();
aabb_min.X = MIN(aabb_min.X, x1);
aabb_min.X = MIN(aabb_min.X, x2);

View file

@ -4,6 +4,8 @@
#include "tarray.h"
#include "vectors.h"
struct FLevelLocals;
namespace hwrenderer
{
@ -35,12 +37,12 @@ struct AABBTreeLine
float dx, dy;
};
// Axis aligned bounding box tree used for ray testing lines.
// Axis aligned bounding box tree used for ray testing treelines.
class LevelAABBTree
{
public:
// Constructs a tree for the current level
LevelAABBTree();
LevelAABBTree(FLevelLocals *lev);
// Shoot a ray from ray_start to ray_end and return the closest hit as a fractional value between 0 and 1. Returns 1 if no line was hit.
double RayTest(const DVector3 &ray_start, const DVector3 &ray_end);
@ -48,14 +50,14 @@ public:
bool Update();
const void *Nodes() const { return nodes.Data(); }
const void *Lines() const { return lines.Data(); }
const void *Lines() const { return treelines.Data(); }
size_t NodesSize() const { return nodes.Size() * sizeof(AABBTreeNode); }
size_t LinesSize() const { return lines.Size() * sizeof(AABBTreeLine); }
size_t LinesSize() const { return treelines.Size() * sizeof(AABBTreeLine); }
const void *DynamicNodes() const { return nodes.Data() + dynamicStartNode; }
const void *DynamicLines() const { return lines.Data() + dynamicStartLine; }
const void *DynamicLines() const { return treelines.Data() + dynamicStartLine; }
size_t DynamicNodesSize() const { return (nodes.Size() - dynamicStartNode) * sizeof(AABBTreeNode); }
size_t DynamicLinesSize() const { return (lines.Size() - dynamicStartLine) * sizeof(AABBTreeLine); }
size_t DynamicLinesSize() const { return (treelines.Size() - dynamicStartLine) * sizeof(AABBTreeLine); }
size_t DynamicNodesOffset() const { return dynamicStartNode * sizeof(AABBTreeNode); }
size_t DynamicLinesOffset() const { return dynamicStartLine * sizeof(AABBTreeLine); }
@ -69,7 +71,7 @@ private:
double IntersectRayLine(const DVector2 &ray_start, const DVector2 &ray_end, int line_index, const DVector2 &raydelta, double rayd, double raydist2);
// Generate a tree node and its children recursively
int GenerateTreeNode(int *lines, int num_lines, const FVector2 *centroids, int *work_buffer);
int GenerateTreeNode(int *treelines, int num_lines, const FVector2 *centroids, int *work_buffer);
TArray<int> FindNodePath(unsigned int line, unsigned int node);
@ -77,12 +79,13 @@ private:
TArray<AABBTreeNode> nodes;
// Line segments for the leaf nodes in the tree.
TArray<AABBTreeLine> lines;
TArray<AABBTreeLine> treelines;
int dynamicStartNode = 0;
int dynamicStartLine = 0;
TArray<int> mapLines;
FLevelLocals *Level;
};
} // namespace

View file

@ -141,23 +141,23 @@ void IShadowMap::CollectLights()
}
}
bool IShadowMap::ValidateAABBTree()
bool IShadowMap::ValidateAABBTree(FLevelLocals *Level)
{
// Just comparing the level info is not enough. If two MAPINFO-less levels get played after each other,
// they can both refer to the same default level info.
if (level.info != mLastLevel && (level.nodes.Size() != mLastNumNodes || level.segs.Size() != mLastNumSegs))
if (Level->info != mLastLevel && (Level->nodes.Size() != mLastNumNodes || Level->segs.Size() != mLastNumSegs))
{
mAABBTree.reset();
mLastLevel = level.info;
mLastNumNodes = level.nodes.Size();
mLastNumSegs = level.segs.Size();
mLastLevel = Level->info;
mLastNumNodes = Level->nodes.Size();
mLastNumSegs = Level->segs.Size();
}
if (mAABBTree)
return true;
mAABBTree.reset(new hwrenderer::LevelAABBTree());
mAABBTree.reset(new hwrenderer::LevelAABBTree(Level));
return false;
}
@ -194,7 +194,7 @@ void IShadowMap::UploadLights()
void IShadowMap::UploadAABBTree()
{
if (!ValidateAABBTree())
if (!ValidateAABBTree(&level))
{
if (!mNodesBuffer)
mNodesBuffer = screen->CreateDataBuffer(2, true);

View file

@ -8,6 +8,7 @@
struct FDynamicLight;
struct level_info_t;
class IDataBuffer;
struct FLevelLocals;
class IShadowMap
{
@ -33,7 +34,7 @@ public:
protected:
void CollectLights();
bool ValidateAABBTree();
bool ValidateAABBTree(FLevelLocals *lev);
// Upload the AABB-tree to the GPU
void UploadAABBTree();

View file

@ -117,7 +117,6 @@ static void PlayerLandedOnThing (AActor *mo, AActor *onmobj);
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
extern int BotWTG;
EXTERN_CVAR (Int, cl_rockettrails)
// PRIVATE DATA DEFINITIONS ------------------------------------------------