Loading...
Searching...
No Matches
TextToMesh.hpp
1#pragma once
2#include "TransformHelper.hpp"
3
4#include <ossia/dataflow/geometry_port.hpp>
5
6#include <Gfx/Graph/GpuResourceRegistry.hpp>
7
8#include <Threedim/TinyObj.hpp>
9#include <halp/controls.hpp>
10#include <halp/meta.hpp>
11
12#include <cstdint>
13#include <memory>
14
15class QRhiResourceUpdateBatch;
16
17namespace score::gfx
18{
19class RenderList;
20struct Edge;
21}
22
23namespace Threedim
24{
25
26// Rasterize text into 3D geometry. Each glyph is converted to a
27// QPainterPath, flattened into polygons, and tessellated via simple
28// ear-clipping. Output is a scene_spec containing one scene_node with
29// one mesh_component whose vertices describe the text in the XY plane
30// (normal = +Z) around the origin.
31//
32// Limitations (v1):
33// - Holes are NOT handled. Glyphs with interior holes ("O", "D", "o",
34// "P" counter, etc.) render as solid shapes. Fix planned by adding
35// earcut.hpp or hole-bridging to the tessellator.
36// - Extrusion = 0 (flat). A later revision will extrude along -Z
37// with properly-oriented side walls.
38// - Tangents are synthesized as (1, 0, 0, 1) by ScenePreprocessor's
39// fallback — no per-vertex tangent computed here.
40//
41// Designed for VJ / title-card use rather than typography; single-line
42// inputs only. For paragraph text, use TextToTexture on a quad.
44{
45public:
46 halp_meta(name, "Text to Mesh")
47 halp_meta(category, "Visuals/3D/Text")
48 halp_meta(c_name, "text_to_mesh")
49 halp_meta(authors, "ossia team")
50 halp_meta(
51 manual_url,
52 "https://ossia.io/score-docs/processes/text-to-mesh.html")
53 halp_meta(uuid, "c8f2a4d5-6e9b-4d3a-b7f1-5c4e2d8a9f6b")
54
55 struct ins
56 {
57 // Port-driven rebuild: controls trigger TextToMesh::rebuild() via
58 // their update() callbacks; operator()() just republishes m_state.
59 struct : halp::lineedit<"Text", "Hello">
60 { void update(TextToMesh& n) { n.rebuild(); } } text;
61 struct : halp::lineedit<"Font family", "Sans">
62 { void update(TextToMesh& n) { n.rebuild(); } } font_family;
63 struct : halp::spinbox_i32<"Font size", halp::irange{4, 512, 72}>
64 { void update(TextToMesh& n) { n.rebuild(); } } font_size;
65 struct : halp::toggle<"Bold">
66 { void update(TextToMesh& n) { n.rebuild(); } } bold;
67 struct : halp::toggle<"Italic">
68 { void update(TextToMesh& n) { n.rebuild(); } } italic;
69 // World-space height of a capital 'H'. Glyph paths come out in
70 // pixel units from Qt; we scale them to this target so the mesh
71 // lives at a sensible world scale regardless of font_size.
72 struct : halp::hslider_f32<"Height", halp::range{0.01, 100., 1.}>
73 { void update(TextToMesh& n) { n.rebuild(); } } height;
74 // Centers the text around the origin on the X axis (vs. left-align
75 // at X=0). Useful for title cards.
76 struct : halp::toggle<"Center X">
77 { void update(TextToMesh& n) { n.rebuild(); } } center_x;
78
79 struct : PositionControl
80 { void update(TextToMesh& n) { n.rebuild(); } } position;
81 struct : RotationControl
82 { void update(TextToMesh& n) { n.rebuild(); } } rotation;
83 struct : ScaleControl
84 { void update(TextToMesh& n) { n.rebuild(); } } scale;
85 } inputs;
86
87 struct outs
88 {
89 struct
90 {
91 halp_meta(name, "Scene Out");
92 ossia::scene_spec scene;
93 uint8_t dirty{0};
94 } scene_out;
95 } outputs;
96
97 void rebuild();
98 void operator()();
99
100 void init(score::gfx::RenderList& r, QRhiResourceUpdateBatch& res);
101 void update(
102 score::gfx::RenderList& r, QRhiResourceUpdateBatch& res,
104 void release(score::gfx::RenderList& r);
105
106 std::shared_ptr<ossia::scene_state> m_wrapped_state;
107 CachedTRS m_cachedTRS{};
108 // Mesh-rebuild cache — expensive tessellation only re-runs when text
109 // or font parameters actually change.
110 std::string m_cached_text;
111 std::string m_cached_family;
112 int m_cached_size{-1};
113 bool m_cached_bold{false};
114 bool m_cached_italic{false};
115 float m_cached_height{-1.f};
116 bool m_cached_center{false};
117 std::shared_ptr<ossia::mesh_component> m_cached_mesh;
118 int64_t m_version_counter{0};
119 uint8_t m_pending_dirty{0xFF};
120
121 score::gfx::GpuResourceRegistry::Slot raw_transform_slot;
122 ossia::gpu_slot_ref m_xform_ref{};
123};
124
125}
Definition TextToMesh.hpp:44
List of nodes to be rendered to an output.
Definition RenderList.hpp:30
Graphics rendering pipeline for ossia score.
Definition Filter/PreviewWidget.hpp:11
Definition TransformHelper.hpp:26
Definition TinyObj.hpp:98
Definition TinyObj.hpp:103
Definition TinyObj.hpp:107
Definition TextToMesh.hpp:56
Definition TextToMesh.hpp:88
Connection between two score::gfx::Port.
Definition score-plugin-gfx/Gfx/Graph/Utils.hpp:103
Definition GpuResourceRegistry.hpp:84