Skip to content

Commit 2b406cb

Browse files
Improve font rendering and add batch binary file reading
Refactored font character geometry to use floating point vectors for size and bearing, and improved transform calculations for UI elements and text rendering. Added a new IoEngine::readFilesBinary method for batch reading binary files from a directory. Updated SMD animation loader for better performance and correctness. Minor shader and debug improvements, and updated GLFW submodule.
1 parent 6cfb426 commit 2b406cb

File tree

7 files changed

+272
-58
lines changed

7 files changed

+272
-58
lines changed

default_assets/shaders/defaultui.glsl

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,11 @@ void main()
1414

1515
texCoords.y = 1.0 - texCoords.y;
1616

17-
gl_Position = _internalProj * _internalModel * vec4(aPos,0, 1.0);
17+
vec4 p = _internalProj * _internalModel * vec4(aPos,0, 1.0);
18+
19+
p.z = 0;
20+
21+
gl_Position = p;
1822
}
1923
#define __ENDSHADER
2024

ext/glfw

include/borealis/gfx/ui.hpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,14 @@ namespace brl
3535
void earlyUpdate() override;
3636
void lateUpdate() override;
3737

38+
static GfxCanvas* mainCanvas;
39+
3840
private:
3941
friend struct GfxImage;
4042
friend struct GfxUIElement;
4143
friend struct GfxTextRenderer;
4244
friend GfxEngine;
4345

44-
static GfxCanvas* mainCanvas;
4546

4647
void insertDrawCall(const GfxUIDrawCall call);
4748

@@ -129,9 +130,9 @@ namespace brl
129130
struct GfxFontCharacter : GfxTexture
130131
{
131132
GfxFontCharacter() = default;
132-
GfxFontCharacter(unsigned int id, glm::ivec2 s, glm::ivec2 b, unsigned int adv);
133-
glm::ivec2 size; // Size of glyph
134-
glm::ivec2 bearing; // Offset from baseline to left/top of glyph
133+
GfxFontCharacter(unsigned int id, glm::vec2 s, glm::vec2 b, unsigned int adv);
134+
glm::vec2 size; // Size of glyph
135+
glm::vec2 bearing; // Offset from baseline to left/top of glyph
135136
unsigned int advanceOffset; // Offset to advance to next glyph
136137

137138
GfxAttribBuffer* charVAO = nullptr;
@@ -154,6 +155,7 @@ namespace brl
154155
std::string text;
155156

156157
void start() override;
158+
void debugPrintCharacterInfo();
157159
void lateUpdate() override;
158160

159161
private:

include/borealis/util/io.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ namespace brl
3838
void print(std::string s);
3939
IoFile readFileBinary(std::string path);
4040
std::string readFileString(std::string path);
41+
std::vector<IoFile> readFilesBinary(std::string directory);
4142
void shutdown();
4243
};
4344

@@ -47,6 +48,10 @@ namespace brl
4748
{
4849
return IoEngine::engine->readFileString(path);
4950
}
51+
inline std::vector<IoFile> readFilesBinary(std::string directory)
52+
{
53+
return IoEngine::engine->readFilesBinary(directory);
54+
}
5055

5156

5257
} // namespace brl

src/brl/gfx/model.cpp

Lines changed: 119 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include "borealis/debug/debug.hpp"
99
#include "borealis/gfx/engine.hpp"
1010
#include "borealis/gfx/shader.hpp"
11+
#include "glm/gtx/euler_angles.hpp"
1112
#include "glm/gtx/matrix_decompose.hpp"
1213

1314
static brl::GfxShaderProgram* defaultSkinningShader = nullptr;
@@ -104,6 +105,9 @@ brl::GfxShaderProgram* GetSkinningShader()
104105
return defaultSkinningShader;
105106
}
106107

108+
std::map<std::string, brl::GfxAnimation*> brl::GfxAnimation::cachedAnimations;
109+
110+
107111
brl::GfxAnimation *brl::GfxAnimation::loadAnimation(std::string path)
108112
{
109113
if (cachedAnimations.contains(path))
@@ -132,53 +136,146 @@ std::vector<std::string> splitFileByCharacter(const std::string& data, char deli
132136
brl::GfxAnimation::GfxAnimation(std::string path)
133137
{
134138

135-
if (path.ends_with(".smd")) {
139+
if (path.ends_with(".smd"))
140+
{
136141
// smd loading
137-
138142
std::string data = brl::readFileString(path);
139-
140143
const auto& lines = splitFileByCharacter(data);
141144

142-
int version = 0;
143-
144-
enum smd_stage {
145+
enum smd_stage
146+
{
145147
none,
146-
nodes
148+
nodes,
149+
skeleton
147150
};
148151
smd_stage cur_stage = none;
149152

150-
for (const auto & line : lines) {
151-
if (line.starts_with("version")) {
152-
using namespace std::literals::string_literals; // Bring the "s" suffix into scope
153+
struct smd_frame
154+
{
155+
int frame;
156+
glm::vec3 position;
157+
glm::quat rotation;
158+
};
159+
160+
struct smd_channel
161+
{
162+
std::vector<smd_frame> frames;
163+
};
164+
165+
struct smd_bone
166+
{
167+
int id = 0;
168+
std::string name;
169+
int parent_bone = -1;
170+
smd_channel channel;
171+
};
172+
173+
std::vector<smd_bone> bones;
174+
bones.reserve(64); // Reserve reasonable initial capacity
153175

154-
std::string verStr = line.substr(("version "s).length(),1);
176+
int max_frame = 0;
177+
int current_time = 0;
155178

156-
version = std::atoi(verStr.c_str());
179+
for (const auto& line : lines)
180+
{
181+
if (line.empty())
157182
continue;
158-
}
159183

160-
if (line.starts_with("nodes")) {
184+
// Fast stage detection using first character
185+
char first_char = line[0];
186+
187+
if (first_char == 'v')
188+
{ // version
189+
continue; // Version not used, skip parsing
190+
}
191+
else if (first_char == 'n')
192+
{ // nodes
161193
cur_stage = nodes;
162194
continue;
163195
}
164-
165-
if (line.starts_with("end")) {
196+
else if (first_char == 's')
197+
{ // skeleton
198+
cur_stage = skeleton;
199+
continue;
200+
}
201+
else if (first_char == 'e')
202+
{ // end
166203
cur_stage = none;
167204
continue;
168205
}
169206

170-
if (cur_stage == nodes) {
171-
auto data = splitFileByCharacter(line,' ');
207+
if (cur_stage == nodes)
208+
{
209+
auto data = splitFileByCharacter(line, ' ');
172210

173-
int id = std::atoi(data[0].c_str());
174-
std::string name = data[1].c_str();
175-
int parentId = std::atoi(data[2].c_str());
211+
smd_bone bone;
212+
bone.id = std::atoi(data[0].c_str());
213+
bone.name = std::move(data[1]);
214+
bone.parent_bone = std::atoi(data[2].c_str());
215+
bone.channel.frames.reserve(max_frame > 0 ? max_frame + 1 : 32);
176216

217+
bones.push_back(std::move(bone));
218+
}
219+
else if (cur_stage == skeleton)
220+
{
221+
if (first_char == 't')
222+
{ // time
223+
// Fast parse: skip "time " prefix
224+
current_time = std::atoi(line.c_str() + 5);
225+
max_frame = std::max(max_frame, current_time);
226+
}
227+
else
228+
{
229+
auto data = splitFileByCharacter(line, ' ');
230+
int id = std::atoi(data[0].c_str());
231+
232+
smd_frame f;
233+
f.frame = current_time;
234+
f.position =
235+
glm::vec3(std::atof(data[1].c_str()), std::atof(data[2].c_str()), std::atof(data[3].c_str()));
236+
237+
glm::vec3 angles(std::atof(data[4].c_str()), std::atof(data[5].c_str()),
238+
std::atof(data[6].c_str()));
239+
240+
// Correct SMD quaternion conversion (XYZ order)
241+
f.rotation = glm::quat(angles);
242+
243+
bones[id].channel.frames.push_back(std::move(f));
244+
}
177245
}
178246
}
179247

180-
}
248+
length = 1.0f;
249+
250+
// Reserve space for channels
251+
channels.reserve(bones.size() * 2);
252+
253+
const float inv_max_frame = max_frame > 0 ? 1.0f / static_cast<float>(max_frame) : 0.0f;
181254

255+
for (auto& bone : bones)
256+
{
257+
if (bone.channel.frames.empty())
258+
continue;
259+
260+
Channel positionChannel{bone.id, ChannelInterpolation::LINEAR, TRANSLATION};
261+
Channel rotationChannel{bone.id, ChannelInterpolation::LINEAR, ROTATION};
262+
263+
size_t frame_count = bone.channel.frames.size();
264+
positionChannel.frames.reserve(frame_count);
265+
rotationChannel.frames.reserve(frame_count);
266+
267+
for (const smd_frame& frame : bone.channel.frames)
268+
{
269+
float time = static_cast<float>(frame.frame) * inv_max_frame;
270+
271+
positionChannel.frames.push_back(new Vec3AnimationFrame{time, frame.position});
272+
rotationChannel.frames.push_back(new QuatAnimationFrame{time, frame.rotation});
273+
}
274+
275+
channels.push_back(std::move(positionChannel));
276+
channels.push_back(std::move(rotationChannel));
277+
}
278+
}
182279
}
183280

184281
brl::GfxSubMesh::~GfxSubMesh()

0 commit comments

Comments
 (0)