Skip to content

Commit

Permalink
Gloom: Sector polygon manipulation in the editor
Browse files Browse the repository at this point in the history
Not quite working right, map data needs tweaking...
  • Loading branch information
skyjake committed Sep 1, 2019
1 parent 44afdd2 commit eb551a1
Show file tree
Hide file tree
Showing 4 changed files with 223 additions and 30 deletions.
147 changes: 136 additions & 11 deletions doomsday/tests/test_gloom/gloom/render/mapbuild.cpp
Expand Up @@ -20,6 +20,8 @@
#include "polygon.h"
#include "../geomath.h"

#include <array>

using namespace de;

namespace gloom {
Expand Down Expand Up @@ -82,6 +84,37 @@ DENG2_PIMPL_NOREF(MapBuild)
Buffer::Vertices verts;
Buffer::Indices indices;

using PlaneVerts = std::array<QHash<ID, Vector3f>, 2>;
auto projectPlanes = [this](const Sector &sec) {
const Volume *vols[2]{&map.volume(sec.volumes.first()),
&map.volume(sec.volumes.last())};
PlaneVerts planeVerts;
for (int p = 0; p < 2; ++p)
{
const Plane &plane = map.plane(vols[p]->planes[p]);
for (const ID lineId : sec.lines)
{
const Line &line = map.line(lineId);
for (const ID pointId : line.points)
{
if (!planeVerts[p].contains(pointId))
{
planeVerts[p].insert(pointId, projectPoint(pointId, plane));
}
}
}
}
return planeVerts;
};
QHash<ID, PlaneVerts> sectorPlaneVerts;

// Project each sector's points to their floor and ceiling planes.
for (const ID sectorId : map.sectors().keys())
{
sectorPlaneVerts.insert(sectorId, projectPlanes(map.sector(sectorId)));
}


for (const ID sectorId : map.sectors().keys())
{
const Sector &sector = map.sector(sectorId);
Expand All @@ -97,16 +130,16 @@ DENG2_PIMPL_NOREF(MapBuild)
const auto convexParts = map.sectorPolygon(sectorId).splitConvexParts();

// Each volume is built separately.
for (const ID volId : sector.volumes)
//for (const ID volId : sector.volumes)
{
const Volume &volume = map.volumes()[volId];
/*const Volume &volume = map.volume(volId);
QHash<ID, Vector3f> planeVerts[2];
for (int p = 0; p < 2; ++p)
{
const Plane &plane = map.planes()[volume.planes[p]];
const Plane &plane = map.plane(volume.planes[p]);
for (const ID lineId : sector.lines)
{
const Line &line = map.lines()[lineId];
const Line &line = map.line(lineId);
for (const ID pointId : line.points)
{
if (!planeVerts[p].contains(pointId))
Expand All @@ -115,7 +148,9 @@ DENG2_PIMPL_NOREF(MapBuild)
}
}
}
}
}*/

const auto &planeVerts = sectorPlaneVerts[sectorId];

// Build the floor and ceiling of this volume.
{
Expand All @@ -127,7 +162,7 @@ DENG2_PIMPL_NOREF(MapBuild)
f.normal = Vector3f(0, 1, 0);
f.flags = MapVertex::WorldSpaceXZToTexCoords;

c.texture = textures["world.stone"];
c.texture = textures["world.dirt"];
c.normal = Vector3f(0, -1, 0);
c.flags = MapVertex::WorldSpaceXZToTexCoords;

Expand Down Expand Up @@ -165,18 +200,108 @@ DENG2_PIMPL_NOREF(MapBuild)
}
}

auto makeQuad = [this, &indices, &verts](const String & textureName,
const Vector3f &normal,
uint32_t flags,
const Vector3f &p1,
const Vector3f &p2,
const Vector3f &p3,
const Vector3f &p4,
const Vector2f &uv1,
const Vector2f &uv2,
const Vector2f &uv3,
const Vector2f &uv4) {
const Buffer::Index baseIndex = Buffer::Index(verts.size());
indices << baseIndex
<< baseIndex + 3
<< baseIndex + 2
<< baseIndex
<< baseIndex + 1
<< baseIndex + 3;

Buffer::Type v;

v.texture = textures[textureName];
v.normal = normal;
v.flags = flags;

v.pos = p1;
v.texCoord = uv1;
verts << v;

v.pos = p2;
v.texCoord = uv2;
verts << v;

v.pos = p3;
v.texCoord = uv3;
verts << v;

v.pos = p4;
v.texCoord = uv4;
verts << v;
};

// Build the walls.
for (const ID lineId : sector.lines)
{
const Line & line = map.lines()[lineId];
const ID start = line.points[0];
const ID end = line.points[1];
const Line &line = map.line(lineId);

if (line.isSelfRef()) continue;

const int dir = line.sectors[0] == sectorId? 1 : 0;
const ID start = line.points[dir^1];
const ID end = line.points[dir];
const Vector3f normal = normalVector(line);
const float length = float((planeVerts[0][end] - planeVerts[0][start]).length());
const float heights[2] = {planeVerts[1][start].y - planeVerts[0][start].y,
planeVerts[1][end].y - planeVerts[0][end].y};

const Buffer::Index baseIndex = Buffer::Index(verts.size());
if (!line.isTwoSided())
{
makeQuad("world.stone",
normal,
0,
planeVerts[0][start],
planeVerts[0][end],
planeVerts[1][start],
planeVerts[1][end],
Vector2f(0, 0),
Vector2f(length, 0),
Vector2f(0, heights[0]),
Vector2f(length, heights[1]));
}
else if (dir)
{
const ID backSectorId = line.sectors[dir];
//const Sector & backSector = map.sector(backSectorId);
const PlaneVerts &backPlaneVerts = sectorPlaneVerts[backSectorId];

makeQuad("world.stone",
normal,
0,
planeVerts[0][start],
planeVerts[0][end],
backPlaneVerts[0][start],
backPlaneVerts[0][end],
Vector2f(0, 0),
Vector2f(length, 0),
Vector2f(0, backPlaneVerts[0][start].y - planeVerts[0][start].y),
Vector2f(length, backPlaneVerts[0][end].y - planeVerts[0][end].y));
makeQuad("world.stone",
normal,
0,
backPlaneVerts[1][start],
backPlaneVerts[1][end],
planeVerts[1][start],
planeVerts[1][end],
Vector2f(0, 0),
Vector2f(length, 0),
Vector2f(0, planeVerts[1][start].y - backPlaneVerts[1][start].y),
Vector2f(length, planeVerts[1][end].y - backPlaneVerts[1][end].y));
}

/* const Buffer::Index baseIndex = Buffer::Index(verts.size());
indices << baseIndex
<< baseIndex + 3
<< baseIndex + 2
Expand Down Expand Up @@ -204,7 +329,7 @@ DENG2_PIMPL_NOREF(MapBuild)
v.pos = planeVerts[1][end];
v.texCoord = Vector2f(length, heights[1]);
verts << v;
verts << v;*/
}
}
}
Expand Down
56 changes: 50 additions & 6 deletions doomsday/tests/test_gloom/gloom/world/map.cpp
Expand Up @@ -168,6 +168,23 @@ void Map::removeInvalid()
iter.remove();
continue;
}
// Merge lines that share endpoints.
for (ID id : d->lines.keys())
{
Line &other = Map::line(id);
if (line.isOneSided() && other.isOneSided() && other.points[1] == line.points[0] &&
other.points[0] == line.points[1])
{
other.sectors[1] = line.sectors[0];
// Sectors referencing the line must be updated.
for (Sector &sec : d->sectors)
{
sec.replaceLine(iter.key(), id);
}
iter.remove();
break;
}
}
}
}

Expand Down Expand Up @@ -358,13 +375,32 @@ geo::Polygon Map::sectorPolygon(ID sectorId) const
{
const auto &sec = sector(sectorId);
geo::Polygon poly;
//ID prevPointId = 0;
ID atPoint;

//const int order[2][2] = {{ 0, 1 }, { 1, 0 }};
for (ID lineId : sec.lines)
{
const auto &line = Map::line(lineId);
const int idx = (line.sectors[0] == sectorId ? 0 : 1);
const ID pointId = line.points[idx];

const auto &line = Map::line(lineId);
const int dir = (line.sectors[0] == sectorId ? 0 : 1);
/*
ID pointId = line.points[idx];
if (line.points[idx^1] == prevPointId)
{
pointId = line.points[idx^1];
}
poly.points << geo::Polygon::Point{d->points[pointId], pointId};
prevPointId = pointId;
*/
/*for (int idx : order[dir])
{
ID pointId = line.points[idx];
if (prevPointId != pointId)
{
poly.points << geo::Polygon::Point{d->points[pointId], pointId};
}
prevPointId = pointId;
}*/
}
poly.updateBounds();
return poly;
Expand Down Expand Up @@ -542,12 +578,20 @@ void Map::deserialize(const Block &data)
for (auto i = volumes.begin(); i != volumes.end(); ++i)
{
const auto obj = i.value().toHash();
const auto planes = variantListToIDList(obj["pln"].toList());
d->volumes.insert(getId(i.key()), Volume{{idNum(planes[0]), idNum(planes[1])}});
const IDList planes = variantListToIDList(obj["pln"].toList());
d->volumes.insert(getId(i.key()), Volume{{planes[0], planes[1]}});
}
}

removeInvalid();
}

void Sector::replaceLine(ID oldId, ID newId)
{
for (int i = 0; i < lines.size(); ++i)
{
if (lines[i] == oldId) lines[i] = newId;
}
}

} // namespace gloom
15 changes: 15 additions & 0 deletions doomsday/tests/test_gloom/gloom/world/map.h
Expand Up @@ -34,6 +34,21 @@ struct Line
{
ID points[2];
ID sectors[2]; // front and back

bool isSelfRef() const
{
return sectors[0] == sectors[1];
}

bool isOneSided() const
{
return !sectors[0] || !sectors[1];
}

bool isTwoSided() const
{
return sectors[0] && sectors[1];
}
};
struct Plane
{
Expand Down
35 changes: 22 additions & 13 deletions doomsday/tests/test_gloom/src/editor.cpp
Expand Up @@ -386,19 +386,26 @@ DENG2_PIMPL(Editor)
while (remaining.size())
{
// Find the next line.
for (QMutableListIterator<ID> iter(remaining); iter.hasNext(); )
bool found = false;
for (int sdir = 0; sdir < 2; ++sdir) // prefer successors with line fwd dir
{
Line &suc = map.line(iter.next());
if (suc.points[0] == atPoint || suc.points[1] == atPoint)
for (QMutableListIterator<ID> iter(remaining); iter.hasNext(); )
{
sorted << iter.value();
const int dir = suc.points[0] == atPoint? 1 : 0;
atPoint = suc.points[dir];
suc.sectors[dir^1] = sectorId;
iter.remove();
break;
Line &suc = map.line(iter.next());
if (suc.points[sdir] == atPoint)
{
sorted << iter.value();
//const int dir = suc.points[sdir] == atPoint? 1 : 0;
atPoint = suc.points[sdir^1];
suc.sectors[sdir] = sectorId;
iter.remove();
found = true;
break;
}
}
if (found) break;
}
if (!found) return false;
}

// Complete.
Expand Down Expand Up @@ -906,12 +913,14 @@ void Editor::paintEvent(QPaintEvent *)
const ID id = i.key();
const auto &sector = i.value();

const auto geoPoly = d->map.sectorPolygon(id);

QPolygonF poly;
for (ID lineId : sector.lines)
for (const auto &pp : geoPoly.points)
{
const auto &line = mapLines[lineId];
int index = (line.sectors[0] == id? 0 : 1);
poly.append(d->worldToView(mapPoints[line.points[index]]));
//const auto &line = mapLines[lineId];
//int index = (line.sectors[0] == id? 0 : 1);
poly.append(d->worldToView(pp.pos)); //mapPoints[line.points[index]]));
}
if (d->selection.contains(id))
{
Expand Down

0 comments on commit eb551a1

Please sign in to comment.