Cogs.Core
AnnotationAxisSystem.cpp
1#include "AnnotationAxisSystem.h"
2
3#include "Context.h"
4
5#include "Systems/Core/CameraSystem.h"
6#include "Systems/Core/TransformSystem.h"
7
8#include "Components/Core/TextComponent.h"
9
10
12{
13 const auto cameraComponent = context->cameraSystem->getMainCamera();
14 const auto & cameraData = context->cameraSystem->getData(cameraComponent);
15
16 for (const auto & component : pool) {
17 if (!component.isActive()) continue;
18
19 if (component.hasChanged()) {
20 auto textComponent = component.getComponent<TextComponent>();
21
22 // propagate clearing to text renderer component.
23 if (component.positions.empty() || !std::isfinite(component.distance)) {
24 textComponent->texts.clear();
25 textComponent->positions.clear();
26 textComponent->setChanged();
27 }
28 }
29
30 if (!component.positions.empty() && std::isfinite(component.distance)) {
31 auto textComponent = component.getComponent<TextComponent>();
32
33 std::vector<int> indexes;
34
35 // position label anchor
36 if (component.viewDependentAnchor) {
37 const glm::mat3 M(cameraData.viewMatrix * context->transformSystem->getLocalToWorld(component.getComponent<TransformComponent>()));
38 glm::vec3 d = component.viewDependentAnchorReference * glm::inverse(M);
39 float scale = glm::determinant(M);
40
41 if (d.x < -0.25f * scale) {
42 textComponent->horizontalJustification = HorizontalJustification::Left;
43 } else if (d.x > 0.25f * scale) {
44 textComponent->horizontalJustification = HorizontalJustification::Right;
45 } else {
46 textComponent->horizontalJustification = HorizontalJustification::None;
47 }
48
49 if (d.y < -0.25f * scale) {
50 textComponent->verticalAlignment = VerticalAlignment::Top;
51 } else if (d.y > 0.25f * scale) {
52 textComponent->verticalAlignment = VerticalAlignment::Bottom;
53 } else {
54 textComponent->verticalAlignment = VerticalAlignment::Center;
55 }
56 }
57
58 float distance = component.distance;
59
60 addAnnotations(0,
61 indexes,
62 cameraData.viewProjection * context->transformSystem->getLocalToWorld(component.getComponent<TransformComponent>()),
63 cameraComponent->viewportSize,
64 distance,
65 component.positions.data(),
66 0,
67 static_cast<int>(component.positions.size()) - 1);
68
69
70 textComponent->texts.resize(indexes.size());
71 textComponent->positions.resize(indexes.size());
72
73 for (size_t i = 0; i < indexes.size(); ++i) {
74 textComponent->texts[i] = component.strings[indexes[i]];
75 textComponent->positions[i] = component.positions[indexes[i]];
76 }
77
78 textComponent->positionMode = PositionMode::Local;
79 textComponent->setChanged();
80 }
81 }
82}
83
84float Cogs::Core::AnnotationAxisSystem::getScreenSpaceDistance(const glm::vec3 & p1, const glm::vec3 & p2, const glm::vec2 & viewportSize) const
85{
86 glm::vec3 distanceVector = p2 - p1;
87
88 distanceVector[0] = glm::abs(distanceVector[0]) * viewportSize[0] * 0.5f;
89 distanceVector[1] = glm::abs(distanceVector[1]) * viewportSize[1] * 0.5f;
90 distanceVector[2] = 0.0f;
91
92 return glm::length(distanceVector);
93}
94
95void Cogs::Core::AnnotationAxisSystem::addAnnotations(const int level,
96 std::vector<int> & indexes,
97 const glm::mat4 & projectionMatrix,
98 const glm::vec2 & viewportSize,
99 const float limit,
100 const glm::vec3 * positions,
101 int startIndex,
102 int endIndex)
103{
104 if (startIndex == endIndex) return;
105
106 int mid = (startIndex + endIndex) / 2;
107
108 glm::vec3 p[3];
109 p[0] = positions[startIndex];
110 p[1] = positions[mid];
111 p[2] = positions[endIndex];
112
113 for (int i = 0; i < 3; i++) {
114 glm::vec4 projected = projectionMatrix * glm::vec4(p[i], 1);
115 const float wInv = 1.0f / projected.w;
116 p[i] = glm::vec3(projected.x * wInv, projected.y * wInv, projected.z * wInv);
117 }
118
119 // Handle corner points.
120 if (level == 0) {
121 if (this->getScreenSpaceDistance(p[0], p[2], viewportSize) > limit) {
122 indexes.push_back(startIndex);
123 indexes.push_back(endIndex);
124 }
125 }
126
127 if ((mid == startIndex) || (mid == endIndex)) return;
128
129 float distance = this->getScreenSpaceDistance(p[1], p[0], viewportSize);
130 if (distance > limit) {
131 indexes.push_back(mid);
132 }
133
134 this->addAnnotations(level + 1, indexes, projectionMatrix, viewportSize, limit, positions, startIndex, mid);
135 this->addAnnotations(level + 1, indexes, projectionMatrix, viewportSize, limit, positions, mid, endIndex);
136}
Context * context
Pointer to the Context instance the system lives in.
void update()
Updates the system state to that of the current frame.
ComponentPool< AnnotationAxisComponent > pool
Pool of components managed by the system.
A Context instance contains all the services, systems and runtime components needed to use Cogs.
Definition: Context.h:83
Renders the given text(s) by generating sprites.
Definition: TextComponent.h:77
std::vector< std::string > texts
A set of text strings to render.
Definition: TextComponent.h:91
Defines a 4x4 transformation matrix for the entity and a global offset for root entities.
@ None
None, the text is centered on the position.
@ Right
The rightmost character is placed to the left of the screen position.
@ Left
The leftmost character is placed to the right of the screen position.
@ Bottom
Align the text towards the bottom, making the position minus the font height the baseline of the text...
@ Center
Center the text on the screen position.
@ Top
Align the text towards the top, making the position the baseline of the text.