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

View file

@ -4,6 +4,8 @@
#include "tarray.h" #include "tarray.h"
#include "vectors.h" #include "vectors.h"
struct FLevelLocals;
namespace hwrenderer namespace hwrenderer
{ {
@ -35,12 +37,12 @@ struct AABBTreeLine
float dx, dy; 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 class LevelAABBTree
{ {
public: public:
// Constructs a tree for the current level // 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. // 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); double RayTest(const DVector3 &ray_start, const DVector3 &ray_end);
@ -48,14 +50,14 @@ public:
bool Update(); bool Update();
const void *Nodes() const { return nodes.Data(); } 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 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 *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 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 DynamicNodesOffset() const { return dynamicStartNode * sizeof(AABBTreeNode); }
size_t DynamicLinesOffset() const { return dynamicStartLine * sizeof(AABBTreeLine); } 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); 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 // 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); TArray<int> FindNodePath(unsigned int line, unsigned int node);
@ -77,12 +79,13 @@ private:
TArray<AABBTreeNode> nodes; TArray<AABBTreeNode> nodes;
// Line segments for the leaf nodes in the tree. // Line segments for the leaf nodes in the tree.
TArray<AABBTreeLine> lines; TArray<AABBTreeLine> treelines;
int dynamicStartNode = 0; int dynamicStartNode = 0;
int dynamicStartLine = 0; int dynamicStartLine = 0;
TArray<int> mapLines; TArray<int> mapLines;
FLevelLocals *Level;
}; };
} // namespace } // 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, // 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. // 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(); mAABBTree.reset();
mLastLevel = level.info; mLastLevel = Level->info;
mLastNumNodes = level.nodes.Size(); mLastNumNodes = Level->nodes.Size();
mLastNumSegs = level.segs.Size(); mLastNumSegs = Level->segs.Size();
} }
if (mAABBTree) if (mAABBTree)
return true; return true;
mAABBTree.reset(new hwrenderer::LevelAABBTree()); mAABBTree.reset(new hwrenderer::LevelAABBTree(Level));
return false; return false;
} }
@ -194,7 +194,7 @@ void IShadowMap::UploadLights()
void IShadowMap::UploadAABBTree() void IShadowMap::UploadAABBTree()
{ {
if (!ValidateAABBTree()) if (!ValidateAABBTree(&level))
{ {
if (!mNodesBuffer) if (!mNodesBuffer)
mNodesBuffer = screen->CreateDataBuffer(2, true); mNodesBuffer = screen->CreateDataBuffer(2, true);

View file

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

View file

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