Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ set(mmapper_SRCS
display/MapCanvasRoomDrawer.h
display/RoadIndex.cpp
display/RoadIndex.h
display/RoomRenderTransform.cpp
display/RoomRenderTransform.h
display/RoomSelections.cpp
display/Textures.cpp
display/Textures.h
Expand Down Expand Up @@ -281,6 +283,7 @@ set(mmapper_SRCS
map/InvalidMapOperation.h
map/Map.cpp
map/Map.h
map/localspace.h
map/MapConsistencyError.cpp
map/MapConsistencyError.h
map/ParseTree.cpp
Expand Down Expand Up @@ -308,6 +311,8 @@ set(mmapper_SRCS
map/ServerIdMap.h
map/SpatialDb.cpp
map/SpatialDb.h
map/SpatialIndex.cpp
map/SpatialIndex.h
map/TinyRoomIdSet.cpp
map/TinyRoomIdSet.h
map/World-BaseMap.cpp
Expand Down
77 changes: 48 additions & 29 deletions src/display/Characters.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include "../configuration/configuration.h"
#include "../group/CGroupChar.h"
#include "../group/mmapper2group.h"
#include "../map/Map.h"
#include "../map/roomid.h"
#include "../mapdata/mapdata.h"
#include "../mapdata/roomselection.h"
Expand Down Expand Up @@ -44,32 +45,35 @@ DistantObjectTransform DistantObjectTransform::construct(const glm::vec3 &pos,
return DistantObjectTransform{hint, degrees};
}

bool CharacterBatch::isVisible(const Coordinate &c, float margin) const
bool CharacterBatch::isVisible(const glm::vec3 &pos, const float margin) const
{
return m_mapScreen.isRoomVisible(c, margin);
return glm::distance(m_mapScreen.getProxyLocation(pos, margin), pos) < 0.001f;
}

void CharacterBatch::drawCharacter(const Coordinate &c, const Color color, bool fill)
void CharacterBatch::drawCharacter(const RoomHandle &room, const Color color, const bool fill)
{
const Configuration::CanvasSettings &settings = getConfig().canvas;

const glm::vec3 roomCenter = c.to_vec3() + glm::vec3{0.5f, 0.5f, 0.f};
const int layerDifference = c.z - m_currentLayer;
const auto transform = getRoomRenderTransform(room);
const glm::vec3 &roomCenter = transform.roomCenter;
const glm::vec3 &renderCenter = transform.renderCenter;
const Coordinate &coord = room.getPosition();
const int layerDifference = coord.z - m_currentLayer;

auto &gl = getOpenGL();
gl.setColor(color);

// REVISIT: The margin probably needs to be modified for high-dpi.
const float marginPixels = MapScreen::DEFAULT_MARGIN_PIXELS;
const bool visible = isVisible(c, marginPixels / 2.f);
const bool visible = isVisible(renderCenter, marginPixels / 2.f);
const bool isFar = m_scale <= settings.charBeaconScaleCutoff;
const bool wantBeacons = settings.drawCharBeacons && isFar;
if (!visible) {
static const bool useScreenSpacePlayerArrow = std::invoke([]() -> bool {
auto opt = utils::getEnvBool("MMAPPER_SCREEN_SPACE_ARROW");
return opt ? opt.value() : true;
});
const auto dot = DistantObjectTransform::construct(roomCenter, m_mapScreen, marginPixels);
const auto dot = DistantObjectTransform::construct(renderCenter, m_mapScreen, marginPixels);
// Player is distant
if (useScreenSpacePlayerArrow) {
gl.addScreenSpaceArrow(dot.offset, dot.rotationDegrees, color, fill);
Expand All @@ -86,8 +90,9 @@ void CharacterBatch::drawCharacter(const Coordinate &c, const Color color, bool

const bool differentLayer = layerDifference != 0;
if (differentLayer) {
const glm::vec3 centerOnCurrentLayer{static_cast<glm::vec2>(roomCenter),
static_cast<float>(m_currentLayer)};
const glm::vec3 centerOnCurrentLayer = applyLocalspaceTransform(
transform,
glm::vec3{roomCenter.x, roomCenter.y, static_cast<float>(m_currentLayer)});
// Draw any arrow on the current layer pointing in either up or down
// (this may not make sense graphically in an angled 3D view).
gl.glPushMatrix();
Expand All @@ -100,7 +105,7 @@ void CharacterBatch::drawCharacter(const Coordinate &c, const Color color, bool
}

const bool beacon = visible && !differentLayer && wantBeacons;
gl.drawBox(c, fill, beacon, isFar);
gl.drawBox(coord, transform, fill, beacon, isFar);
}

void CharacterBatch::CharFakeGL::drawPathSegment(const glm::vec3 &p1,
Expand All @@ -110,7 +115,8 @@ void CharacterBatch::CharFakeGL::drawPathSegment(const glm::vec3 &p1,
mmgl::generateLineQuadsSafe(m_pathLineQuads, p1, p2, PATH_LINE_WIDTH, color);
}

void CharacterBatch::drawPreSpammedPath(const Coordinate &c1,
void CharacterBatch::drawPreSpammedPath(const Map &map,
const Coordinate &c1,
const std::vector<Coordinate> &path,
const Color color)
{
Expand All @@ -119,13 +125,19 @@ void CharacterBatch::drawPreSpammedPath(const Coordinate &c1,
}

using TranslatedVerts = std::vector<glm::vec3>;
const auto verts = std::invoke([&c1, &path]() -> TranslatedVerts {
const auto verts = std::invoke([&c1, &path, &map]() -> TranslatedVerts {
TranslatedVerts translated;
translated.reserve(path.size() + 1);

const auto add = [&translated](const Coordinate &c) -> void {
const auto add = [&translated, &map](const Coordinate &c) -> void {
static const glm::vec3 PATH_OFFSET{0.5f, 0.5f, 0.f};
translated.push_back(c.to_vec3() + PATH_OFFSET);
const glm::vec3 pos = c.to_vec3() + PATH_OFFSET;
if (const auto room = map.findRoomHandle(c)) {
const auto transform = getRoomRenderTransform(room);
translated.push_back(applyLocalspaceTransform(transform, pos));
} else {
translated.push_back(pos);
}
};

add(c1);
Expand Down Expand Up @@ -227,10 +239,13 @@ void CharacterBatch::CharFakeGL::drawQuadCommon(const glm::vec2 &in_a,
}

void CharacterBatch::CharFakeGL::drawBox(const Coordinate &coord,
bool fill,
bool beacon,
const RoomRenderTransform &transform,
const bool fill,
const bool beacon,
const bool isFar)
{
bool canFill = fill;
bool canBeacon = beacon;
const bool dontFillRotatedQuads = true;
const bool shrinkRotatedQuads = false; // REVISIT: make this a user option?

Expand All @@ -239,7 +254,10 @@ void CharacterBatch::CharFakeGL::drawBox(const Coordinate &coord,

glPushMatrix();

glTranslatef(coord.to_vec3());
glTranslatef(transform.renderCenter);
const float combinedScale = getCombinedRoomScale(transform);
glScalef(combinedScale, combinedScale, 1.f);
glTranslatef(glm::vec3{-0.5f, -0.5f, 0.f});

if (numAlreadyInRoom != 0) {
// NOTE: use of 45/PI here is NOT a botched conversion to radians;
Expand All @@ -257,9 +275,9 @@ void CharacterBatch::CharFakeGL::drawBox(const Coordinate &coord,
glRotateZ(degrees);
glTranslatef(-quadCenter);
if (dontFillRotatedQuads) {
fill = false; // avoid highlighting the room multiple times
canFill = false; // avoid highlighting the room multiple times
}
beacon = false;
canBeacon = false;
}

// d-c
Expand All @@ -272,8 +290,8 @@ void CharacterBatch::CharFakeGL::drawBox(const Coordinate &coord,

if (isFar) {
const auto options = QuadOptsEnum::OUTLINE
| (fill ? QuadOptsEnum::FILL : QuadOptsEnum::NONE)
| (beacon ? QuadOptsEnum::BEACON : QuadOptsEnum::NONE);
| (canFill ? QuadOptsEnum::FILL : QuadOptsEnum::NONE)
| (canBeacon ? QuadOptsEnum::BEACON : QuadOptsEnum::NONE);
drawQuadCommon(a, b, c, d, options);
} else {
/* ignoring fill for now; that'll require a different icon */
Expand All @@ -289,7 +307,7 @@ void CharacterBatch::CharFakeGL::drawBox(const Coordinate &coord,
addTransformed(c);
addTransformed(d);

if (beacon) {
if (canBeacon) {
drawQuadCommon(a, b, c, d, QuadOptsEnum::BEACON);
}
}
Expand Down Expand Up @@ -406,19 +424,21 @@ void MapCanvas::paintCharacters()
if (const std::optional<RoomId> opt_pos = m_data.getCurrentRoomId()) {
const auto &id = opt_pos.value();
if (const auto room = m_data.findRoomHandle(id)) {
const auto &pos = room.getPosition();
// draw the characters before the current position
characterBatch.incrementCount(pos);
characterBatch.incrementCount(room.getPosition());
drawGroupCharacters(characterBatch);
characterBatch.resetCount(pos);
characterBatch.resetCount(room.getPosition());

// paint char current position
const Color color{getConfig().groupManager.color};
characterBatch.drawCharacter(pos, color);
characterBatch.drawCharacter(room, color);

// paint prespam
const auto prespam = m_data.getPath(id, m_prespammedPath.getQueue());
characterBatch.drawPreSpammedPath(pos, prespam, color);
characterBatch.drawPreSpammedPath(m_data.getCurrentMap(),
room.getPosition(),
prespam,
color);
return;
} else {
// this can happen if the "current room" is deleted
Expand Down Expand Up @@ -463,11 +483,10 @@ void MapCanvas::drawGroupCharacters(CharacterBatch &batch)
}

const RoomId id = r.getId();
const auto &pos = r.getPosition();
const auto color = Color{character.getColor()};
const bool fill = !drawnRoomIds.contains(id);

batch.drawCharacter(pos, color, fill);
batch.drawCharacter(r, color, fill);
drawnRoomIds.insert(id);
}
}
15 changes: 11 additions & 4 deletions src/display/Characters.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "../global/RuleOf5.h"
#include "../global/utils.h"
#include "../map/coordinate.h"
#include "RoomRenderTransform.h"
#include "../opengl/Font.h"
#include "../opengl/OpenGLTypes.h"

Expand All @@ -21,6 +22,7 @@
#include <QColor>

class MapScreen;
class Map;
class OpenGL;
struct MapCanvasTextures;

Expand Down Expand Up @@ -149,7 +151,11 @@ class NODISCARD CharacterBatch final
m = glm::translate(m, v);
}
void drawArrow(bool fill, bool beacon);
void drawBox(const Coordinate &coord, bool fill, bool beacon, bool isFar);
void drawBox(const Coordinate &coord,
const RoomRenderTransform &transform,
bool fill,
bool beacon,
bool isFar);
void addScreenSpaceArrow(const glm::vec3 &pos, float degrees, const Color color, bool fill);
void drawPathSegment(const glm::vec3 &p1, const glm::vec3 &p2, const Color color);

Expand Down Expand Up @@ -204,12 +210,13 @@ class NODISCARD CharacterBatch final

void resetCount(const Coordinate &c) { getOpenGL().clear(c); }

NODISCARD bool isVisible(const Coordinate &c, float margin) const;
NODISCARD bool isVisible(const glm::vec3 &pos, float margin) const;

public:
void drawCharacter(const Coordinate &coordinate, const Color color, bool fill = true);
void drawCharacter(const RoomHandle &room, const Color color, bool fill = true);

void drawPreSpammedPath(const Coordinate &coordinate,
void drawPreSpammedPath(const Map &map,
const Coordinate &coordinate,
const std::vector<Coordinate> &path,
const Color color);

Expand Down
Loading
Loading