- dynamically update polyobj lines

This commit is contained in:
Magnus Norddahl 2018-12-26 14:26:57 +01:00
parent 1e741446d7
commit 094ef39d5f
3 changed files with 89 additions and 3 deletions

View File

@ -44,6 +44,8 @@ LevelAABBTree::LevelAABBTree()
{ {
if (!level.lines[i].backsector) if (!level.lines[i].backsector)
{ {
if (level.lines[i].sidedef[0] && (level.lines[i].sidedef[0]->Flags & WALLF_POLYOBJ))
polylines.Push(i);
line_elements.Push(i); line_elements.Push(i);
} }
} }
@ -69,6 +71,82 @@ LevelAABBTree::LevelAABBTree()
} }
} }
bool LevelAABBTree::Update()
{
bool modified = false;
for (unsigned int ii = 0; ii < polylines.Size(); ii++)
{
int i = polylines[ii];
const auto &line = level.lines[i];
AABBTreeLine treeline;
treeline.x = (float)line.v1->fX();
treeline.y = (float)line.v1->fY();
treeline.dx = (float)line.v2->fX() - treeline.x;
treeline.dy = (float)line.v2->fY() - treeline.y;
if (memcmp(&lines[i], &treeline, sizeof(AABBTreeLine)))
{
TArray<int> path = FindNodePath(i, nodes.Size() - 1);
if (path.Size())
{
float x1 = (float)level.lines[i].v1->fX();
float y1 = (float)level.lines[i].v1->fY();
float x2 = (float)level.lines[i].v2->fX();
float y2 = (float)level.lines[i].v2->fY();
int nodeIndex = path[0];
nodes[nodeIndex].aabb_left = MIN(x1, x2);
nodes[nodeIndex].aabb_right = MAX(x1, x2);
nodes[nodeIndex].aabb_top = MIN(y1, y2);
nodes[nodeIndex].aabb_bottom = MAX(y1, y2);
for (unsigned int j = 1; j < path.Size(); j++)
{
auto &cur = nodes[path[j]];
const auto &left = nodes[cur.left_node];
const auto &right = nodes[cur.right_node];
cur.aabb_left = MIN(left.aabb_left, right.aabb_left);
cur.aabb_top = MIN(left.aabb_top, right.aabb_top);
cur.aabb_right = MAX(left.aabb_right, right.aabb_right);
cur.aabb_bottom = MAX(left.aabb_bottom, right.aabb_bottom);
}
lines[i] = treeline;
modified = true;
}
}
}
return modified;
}
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)
{
return {};
}
TArray<int> path;
if (n.line_index == -1)
{
path = FindNodePath(line, n.left_node);
if (path.Size() == 0)
path = FindNodePath(line, n.right_node);
if (path.Size())
path.Push(node);
}
else if (n.line_index == line)
{
path.Push(node);
}
return path;
}
double LevelAABBTree::RayTest(const DVector3 &ray_start, const DVector3 &ray_end) double LevelAABBTree::RayTest(const DVector3 &ray_start, const DVector3 &ray_end)
{ {
// Precalculate some of the variables used by the ray/line intersection test // Precalculate some of the variables used by the ray/line intersection test

View File

@ -51,6 +51,8 @@ public:
// 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);
bool Update();
private: private:
// Test if a ray overlaps an AABB node or not // Test if a ray overlaps an AABB node or not
bool OverlapRayAABB(const DVector2 &ray_start2d, const DVector2 &ray_end2d, const AABBTreeNode &node); bool OverlapRayAABB(const DVector2 &ray_start2d, const DVector2 &ray_end2d, const AABBTreeNode &node);
@ -60,6 +62,10 @@ private:
// 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 *lines, int num_lines, const FVector2 *centroids, int *work_buffer);
TArray<int> FindNodePath(unsigned int line, unsigned int node);
TArray<int> polylines;
}; };
} // namespace } // namespace

View File

@ -156,7 +156,7 @@ bool IShadowMap::ValidateAABBTree()
} }
if (mAABBTree) if (mAABBTree)
return true; return mAABBTree->Update();
mAABBTree.reset(new hwrenderer::LevelAABBTree()); mAABBTree.reset(new hwrenderer::LevelAABBTree());
return false; return false;
@ -197,10 +197,12 @@ void IShadowMap::UploadAABBTree()
{ {
if (!ValidateAABBTree()) if (!ValidateAABBTree())
{ {
mNodesBuffer = screen->CreateDataBuffer(2, true); if (!mNodesBuffer)
mNodesBuffer = screen->CreateDataBuffer(2, true);
mNodesBuffer->SetData(sizeof(hwrenderer::AABBTreeNode) * mAABBTree->nodes.Size(), &mAABBTree->nodes[0]); mNodesBuffer->SetData(sizeof(hwrenderer::AABBTreeNode) * mAABBTree->nodes.Size(), &mAABBTree->nodes[0]);
mLinesBuffer = screen->CreateDataBuffer(3, true); if (!mLinesBuffer)
mLinesBuffer = screen->CreateDataBuffer(3, true);
mLinesBuffer->SetData(sizeof(hwrenderer::AABBTreeLine) * mAABBTree->lines.Size(), &mAABBTree->lines[0]); mLinesBuffer->SetData(sizeof(hwrenderer::AABBTreeLine) * mAABBTree->lines.Size(), &mAABBTree->lines[0]);
} }
} }