mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-11 07:12:02 +00:00
- dynamically update polyobj lines
This commit is contained in:
parent
1e741446d7
commit
094ef39d5f
3 changed files with 89 additions and 3 deletions
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue