1#include "Text3DSystem.h"
2#include "TransformSystem.h"
4#include "../../Context.h"
5#include "../../Components/Appearance/MaterialComponent.h"
6#include "../../Components/Core/MeshComponent.h"
7#include "../../Components/Core/MeshRenderComponent.h"
8#include "../../Resources/MaterialManager.h"
9#include "../../Resources/MeshManager.h"
10#include "../../Resources/FontManager.h"
11#include "../../Resources/Texture.h"
13#include "Rendering/ICapabilities.h"
14#include "Foundation/Geometry/IndicesGenerator.h"
20 if (textComponent.isValid()) {
21 Font* font = textComponent.fontHandle.resolve();
25 bool materialChanged =
false;
31 if (material->diffuseMap != font->texture) {
32 materialChanged =
true;
36 materialInstance = meshRenderComp->material.resolve();
38 if (materialInstance && (materialInstance->getTextureProperty(materialInstance->material->getTextureKey(
"diffuseMap")).texture.handle != font->texture)) {
39 materialChanged =
true;
46 font->texture->isActive() &&
47 (textComponent.hasChanged() || materialChanged)) {
50 std::vector<glm::vec3> vertices;
51 std::vector<glm::vec2> uvs;
52 std::vector<glm::vec4> colours;
53 size_t glyphCount = 0;
55 for (
const std::string& t : textComponent.texts) {
56 glyphCount += t.size();
58 vertices.reserve(glyphCount * 4);
59 uvs.reserve(glyphCount * 4);
60 colours.reserve(glyphCount * 4);
62 for (
size_t textIdx = 0, textCount = textComponent.texts.size(); textIdx < textCount; ++textIdx) {
63 const std::string& text = textComponent.texts[textIdx];
64 const glm::vec3& position = textComponent.positions[textIdx];
65 const glm::vec3& hAxis = textComponent.hAxes[textIdx];
66 const glm::vec3& vAxis = textComponent.vAxes[textIdx];
67 const glm::vec4& colour = textComponent.colors.empty() ? textComponent.defaultColor : textComponent.colors[textIdx];
68 const Alignment& alignment = textComponent.alignments.empty() ? textComponent.defaultAlignment : textComponent.alignments[textIdx];
70 generateText(vertices, uvs, fontManager, *font, text, position, hAxis, vAxis, alignment);
71 colours.insert(colours.end(), text.size() << 2, colour);
74 std::vector<uint32_t> indices;
75 constexpr float maxfloat = std::numeric_limits<float>::max();
76 glm::vec3 minbounds(maxfloat, maxfloat, maxfloat);
77 glm::vec3 maxbounds(-maxfloat, -maxfloat, -maxfloat);
79 for (glm::vec3& vert : vertices) {
80 minbounds = glm::min(minbounds, vert);
81 maxbounds = glm::max(maxbounds, vert);
86 mesh->
setName(textComponent.getContainer()->getName());
89 mesh->setColors(colours);
93 textComponent.getComponent<
MeshComponent>()->meshHandle = meshHandle;
97 material->diffuseMap = font->texture;
100 else if (materialInstance) {
101 materialInstance->setTextureProperty(
"diffuseMap", font->texture);
102 materialInstance->setTransparent();
104 materialInstance->setVariant(
"Textured",
true);
111float Cogs::Core::Text3DSystem::calcTextWidth(
const FontManager* fontManager,
const Font& font,
const std::string& text) {
115 for (
auto c : text) {
125void Cogs::Core::Text3DSystem::generateText(std::vector<glm::vec3>& vertices,
126 std::vector<glm::vec2>& uvs,
127 const FontManager* fontManager,
129 const std::string& text,
133 Alignment alignment) {
134 float height = glm::length(vAxis);
135 float verticalScale = height / font.size;
136 float horizontalScale = verticalScale * glm::length(hAxis);
137 float textwidth = calcTextWidth(fontManager, font, text) * horizontalScale;
139 hAxis /= glm::length(hAxis);
142 switch (alignment & Alignment::Horizontal) {
143 case Alignment::Center: position -= hAxis * (textwidth * 0.5f);
break;
144 case Alignment::Right: position -= hAxis * textwidth;
break;
147 switch (alignment & Alignment::Vertical) {
148 case Alignment::Middle: position += vAxis * (font.size * verticalScale * 0.5f);
break;
149 case Alignment::Bottom: position += vAxis * (font.size * verticalScale);
break;
153 position -= vAxis * (font.ascent * verticalScale);
155 for (
size_t ii = 0; ii < text.size(); ++ii) {
156 Font::BakedCharacter bc;
160 fontManager->getBakedCharacter(&font, text[ii], x, y, bc);
162 glm::vec3 left = hAxis * (bc.x0 * horizontalScale);
163 glm::vec3 right = hAxis * (bc.x1 * horizontalScale);
164 glm::vec3 up = vAxis * (bc.y0 * verticalScale);
165 glm::vec3 down = vAxis * (bc.y1 * verticalScale);
167 vertices.push_back(position - up + left);
168 vertices.push_back(position - down + left);
169 vertices.push_back(position - up + right);
170 vertices.push_back(position - down + right);
172 uvs.push_back({bc.s0, bc.t0});
173 uvs.push_back({bc.s0, bc.t1});
174 uvs.push_back({bc.s1, bc.t0});
175 uvs.push_back({bc.s1, bc.t1});
void setChanged()
Sets the component to the ComponentFlags::Changed state with carry.
ComponentType * getComponent() const
Context * context
Pointer to the Context instance the system lives in.
void update()
Updates the system state to that of the current frame.
ComponentPool< Text3DComponent > pool
Pool of components managed by the system.
A Context instance contains all the services, systems and runtime components needed to use Cogs.
Font manager responsible for loading, processing and lifetime of Font resources.
ResourceId DefaultRegularFont
Id of the default font.
void getBakedCharacter(const Font *font, int characterIndex, float &x, float &y, Font::BakedCharacter &bakedCharacter) const
Retrieve baked character information for rendering.
Contains a handle to a Mesh resource to use when rendering using the MeshRenderComponent.
Renders the contents of a MeshComponent using the given materials.
ResourceHandle getHandle(const ResourceId id) const
Get a resource handle to the resource with the given id.
Renders the given text(s) as 3D mesh data.
@ Blend
Render with regular alpha blending.
COGSFOUNDATION_API void generateQuadIndices(std::vector< uint32_t > &dest, size_t quadCount, uint32_t vertexNumber, bool sharedVertices)
Generate indices for rendering the specified number of quads from four vertices starting from the giv...
void setChanged(Cogs::Core::Context *context, Cogs::ComponentModel::Component *component, Reflection::FieldId fieldId)
Must be Called after changing a Component field. Mark field changed. Request engine update.
Defines a quad with locations in screen space defined by [x0, y0] and [x1, y1].
Font resources are used to render text with a specific font and size.
Exposes material properties for legacy entities and code.
Material instances represent a specialized Material combined with state for all its buffers and prope...
Meshes contain streams of vertex data in addition to index data and options defining geometry used fo...
void setTexCoords(std::span< const glm::vec2 > texCoords)
Set the texture coordinate data of the Mesh.
void setIndexData(const uint32_t *data, size_t count)
Convenience method for setting index data from a raw pointer to data and count number of elements.
void setBounds(Geometry::BoundingBox box)
Set custom bounds for the mesh.
void setPositions(std::span< const glm::vec3 > positions)
Set the position data of the Mesh.
void setName(const StringView &name)
Set the user friendly name of the resource.
ResourceType * resolve() const
Resolve the handle, returning a pointer to the actual resource.