From 094ef39d5f1a9d017cc454dd178fd534c1e8d7ce Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Wed, 26 Dec 2018 14:26:57 +0100 Subject: [PATCH] - dynamically update polyobj lines --- src/hwrenderer/dynlights/hw_aabbtree.cpp | 78 +++++++++++++++++++++++ src/hwrenderer/dynlights/hw_aabbtree.h | 6 ++ src/hwrenderer/dynlights/hw_shadowmap.cpp | 8 ++- 3 files changed, 89 insertions(+), 3 deletions(-) diff --git a/src/hwrenderer/dynlights/hw_aabbtree.cpp b/src/hwrenderer/dynlights/hw_aabbtree.cpp index 3d2365bf94..a3b68109c9 100644 --- a/src/hwrenderer/dynlights/hw_aabbtree.cpp +++ b/src/hwrenderer/dynlights/hw_aabbtree.cpp @@ -44,6 +44,8 @@ LevelAABBTree::LevelAABBTree() { 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); } } @@ -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 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 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 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) { // Precalculate some of the variables used by the ray/line intersection test diff --git a/src/hwrenderer/dynlights/hw_aabbtree.h b/src/hwrenderer/dynlights/hw_aabbtree.h index 2d820c5e2b..5e6978d213 100644 --- a/src/hwrenderer/dynlights/hw_aabbtree.h +++ b/src/hwrenderer/dynlights/hw_aabbtree.h @@ -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. double RayTest(const DVector3 &ray_start, const DVector3 &ray_end); + bool Update(); + private: // Test if a ray overlaps an AABB node or not 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 int GenerateTreeNode(int *lines, int num_lines, const FVector2 *centroids, int *work_buffer); + + TArray FindNodePath(unsigned int line, unsigned int node); + + TArray polylines; }; } // namespace diff --git a/src/hwrenderer/dynlights/hw_shadowmap.cpp b/src/hwrenderer/dynlights/hw_shadowmap.cpp index 024a5cc975..fda7f9561f 100644 --- a/src/hwrenderer/dynlights/hw_shadowmap.cpp +++ b/src/hwrenderer/dynlights/hw_shadowmap.cpp @@ -156,7 +156,7 @@ bool IShadowMap::ValidateAABBTree() } if (mAABBTree) - return true; + return mAABBTree->Update(); mAABBTree.reset(new hwrenderer::LevelAABBTree()); return false; @@ -197,10 +197,12 @@ void IShadowMap::UploadAABBTree() { 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]); - mLinesBuffer = screen->CreateDataBuffer(3, true); + if (!mLinesBuffer) + mLinesBuffer = screen->CreateDataBuffer(3, true); mLinesBuffer->SetData(sizeof(hwrenderer::AABBTreeLine) * mAABBTree->lines.Size(), &mAABBTree->lines[0]); } }