mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-12-12 21:52:12 +00:00
- pass 'level' as a parameter to AABBTree. Also renamed a few things to make the code easier to read.
This commit is contained in:
parent
a0ce8f2988
commit
3328821a98
5 changed files with 46 additions and 40 deletions
|
@ -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(¢roids[0], true))
|
if (GenerateTree(¢roids[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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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 ------------------------------------------------
|
||||||
|
|
Loading…
Reference in a new issue