Added truetype, with block support.
This commit is contained in:
		@@ -12,6 +12,6 @@ target_sources(${DAWN_TARGET_NAME}
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
# Subdirs
 | 
			
		||||
# add_subdirectory(font)
 | 
			
		||||
add_subdirectory(font)
 | 
			
		||||
add_subdirectory(mesh)
 | 
			
		||||
add_subdirectory(shader)
 | 
			
		||||
							
								
								
									
										9
									
								
								src/dawn/display/font/CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								src/dawn/display/font/CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,9 @@
 | 
			
		||||
# Copyright (c) 2023 Dominic Masters
 | 
			
		||||
# 
 | 
			
		||||
# This software is released under the MIT License.
 | 
			
		||||
# https://opensource.org/licenses/MIT
 | 
			
		||||
 | 
			
		||||
target_sources(${DAWN_TARGET_NAME}
 | 
			
		||||
  PRIVATE
 | 
			
		||||
    TrueTypeTexture.cpp
 | 
			
		||||
)
 | 
			
		||||
							
								
								
									
										15
									
								
								src/dawn/display/font/TrueTypeCharacter.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								src/dawn/display/font/TrueTypeCharacter.hpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,15 @@
 | 
			
		||||
// Copyright (c) 2023 Dominic Masters
 | 
			
		||||
// 
 | 
			
		||||
// This software is released under the MIT License.
 | 
			
		||||
// https://opensource.org/licenses/MIT
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
#include "dawnlibs.hpp"
 | 
			
		||||
 | 
			
		||||
namespace Dawn {
 | 
			
		||||
  struct TrueTypeCharacter {
 | 
			
		||||
    glm::vec2 advance;
 | 
			
		||||
    glm::vec2 size;
 | 
			
		||||
    glm::vec4 quad;
 | 
			
		||||
  };
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										135
									
								
								src/dawn/display/font/TrueTypeTexture.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										135
									
								
								src/dawn/display/font/TrueTypeTexture.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,135 @@
 | 
			
		||||
// Copyright (c) 2023 Dominic Masters
 | 
			
		||||
// 
 | 
			
		||||
// This software is released under the MIT License.
 | 
			
		||||
// https://opensource.org/licenses/MIT
 | 
			
		||||
 | 
			
		||||
#include "TrueTypeTexture.hpp"
 | 
			
		||||
#include "assert/assert.hpp"
 | 
			
		||||
#include "util/Math.hpp"
 | 
			
		||||
 | 
			
		||||
using namespace Dawn;
 | 
			
		||||
 | 
			
		||||
TrueTypeTexture::TrueTypeTexture(
 | 
			
		||||
  FT_Face face,
 | 
			
		||||
  uint32_t fontSize,
 | 
			
		||||
  uint8_t style
 | 
			
		||||
)  :
 | 
			
		||||
  face(face),
 | 
			
		||||
  fontSize(fontSize),
 | 
			
		||||
  style(style)
 | 
			
		||||
{
 | 
			
		||||
  assertTrue(fontSize < 256, "Font size cannot be greater than 256");
 | 
			
		||||
 | 
			
		||||
  texture = std::make_shared<Texture>();
 | 
			
		||||
 | 
			
		||||
  // Set freetype font size prior to baking.
 | 
			
		||||
  if(FT_Set_Pixel_Sizes(face, 0, fontSize)) {
 | 
			
		||||
    assertUnreachable("Failed to set font size");
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  // Set the texture size
 | 
			
		||||
  texture->setSize(
 | 
			
		||||
    4096,
 | 
			
		||||
    4096,
 | 
			
		||||
    TextureFormat::R,
 | 
			
		||||
    TextureDataFormat::UNSIGNED_BYTE
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
  // Texture buffer
 | 
			
		||||
  uint8_t *buffer = new uint8_t[texture->getWidth() * texture->getHeight()];
 | 
			
		||||
  // Fill with zeros
 | 
			
		||||
  std::memset(buffer, 0, texture->getWidth() * texture->getHeight());
 | 
			
		||||
 | 
			
		||||
  size_t offset = 0;
 | 
			
		||||
  struct TrueTypeCharacter info;
 | 
			
		||||
  int32_t textureX = 0, textureY = 0;
 | 
			
		||||
  int32_t rowHeight = 0;
 | 
			
		||||
 | 
			
		||||
  // Character sets
 | 
			
		||||
  std::vector<wchar_t> characterBlocks;
 | 
			
		||||
  // Latin
 | 
			
		||||
  for(wchar_t c = 0x0020; c < 0x007F; c++) characterBlocks.push_back(c);
 | 
			
		||||
  // Latin-1 Supplement
 | 
			
		||||
  for(wchar_t c = 0x00A0; c < 0x00FF; c++) characterBlocks.push_back(c);
 | 
			
		||||
  // Latin Extended-A
 | 
			
		||||
  for(wchar_t c = 0x0100; c < 0x017F; c++) characterBlocks.push_back(c);
 | 
			
		||||
  // Latin Extended-B
 | 
			
		||||
  for(wchar_t c = 0x0180; c < 0x024F; c++) characterBlocks.push_back(c);
 | 
			
		||||
  // Hiragana
 | 
			
		||||
  for(wchar_t c = 0x3040; c < 0x309F; c++) characterBlocks.push_back(c);
 | 
			
		||||
  // Katakana
 | 
			
		||||
  for(wchar_t c = 0x30A0; c < 0x30FF; c++) characterBlocks.push_back(c);
 | 
			
		||||
 | 
			
		||||
  // For each character in the character set
 | 
			
		||||
  for(wchar_t c : characterBlocks) {
 | 
			
		||||
    // Load the character
 | 
			
		||||
    if(FT_Load_Char(face, c, FT_LOAD_RENDER)) {
 | 
			
		||||
      assertUnreachable("Failed to load character (1)");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Store the character information
 | 
			
		||||
    info.advance.x = (float_t)(face->glyph->advance.x >> 6);
 | 
			
		||||
    info.advance.y = (float_t)(face->glyph->advance.y >> 6);
 | 
			
		||||
    info.size = glm::vec2(face->glyph->bitmap.width, face->glyph->bitmap.rows);
 | 
			
		||||
 | 
			
		||||
    // Determine the texture position
 | 
			
		||||
    if(textureX + face->glyph->bitmap.width >= texture->getWidth()) {
 | 
			
		||||
      textureX = 0;
 | 
			
		||||
      textureY += rowHeight + 1;// Tiny gap between rows
 | 
			
		||||
      rowHeight = face->glyph->bitmap.rows;
 | 
			
		||||
    } else {
 | 
			
		||||
      rowHeight = Math::max<int32_t>(rowHeight, face->glyph->bitmap.rows);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Set the quad positions
 | 
			
		||||
    info.quad = glm::vec4(
 | 
			
		||||
      textureX,
 | 
			
		||||
      textureY,
 | 
			
		||||
      textureX + face->glyph->bitmap.width,
 | 
			
		||||
      textureY + face->glyph->bitmap.rows
 | 
			
		||||
    ) / glm::vec4(
 | 
			
		||||
      texture->getWidth(),
 | 
			
		||||
      texture->getHeight(),
 | 
			
		||||
      texture->getWidth(),
 | 
			
		||||
      texture->getHeight()
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    // Store the cached character data.
 | 
			
		||||
    this->characterData[c] = info;
 | 
			
		||||
 | 
			
		||||
    // Determine pixel offset.
 | 
			
		||||
    offset = textureX + (textureY * texture->getWidth());
 | 
			
		||||
    assertTrue(
 | 
			
		||||
      offset + (face->glyph->bitmap.rows * texture->getWidth()) <=
 | 
			
		||||
      texture->getWidth() * texture->getHeight(),
 | 
			
		||||
      "Font texture buffer overflow will occur."
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    // Buffer pixels, we have to do this one row at a time due to the 
 | 
			
		||||
    // differences in width between the glyph and the texture.
 | 
			
		||||
    const size_t countPerRow = face->glyph->bitmap.width;
 | 
			
		||||
    int32_t i = 0;
 | 
			
		||||
    while(i != face->glyph->bitmap.rows) {
 | 
			
		||||
      std::memcpy(
 | 
			
		||||
        buffer + offset + (i * texture->getWidth()),
 | 
			
		||||
        face->glyph->bitmap.buffer + (i * countPerRow),
 | 
			
		||||
        countPerRow
 | 
			
		||||
      );
 | 
			
		||||
      i++;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Increment textureX
 | 
			
		||||
    textureX += face->glyph->bitmap.width + 1;// I add a tiny gap between chars
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  this->texture->buffer(buffer);
 | 
			
		||||
  delete[] buffer;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct TrueTypeCharacter TrueTypeTexture::getCharacterData(wchar_t c) {
 | 
			
		||||
  return this->characterData[c];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TrueTypeTexture::~TrueTypeTexture() {
 | 
			
		||||
  FT_Done_Face(this->face);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										46
									
								
								src/dawn/display/font/TrueTypeTexture.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								src/dawn/display/font/TrueTypeTexture.hpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,46 @@
 | 
			
		||||
// Copyright (c) 2023 Dominic Masters
 | 
			
		||||
// 
 | 
			
		||||
// This software is released under the MIT License.
 | 
			
		||||
// https://opensource.org/licenses/MIT
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
#include "display/Texture.hpp"
 | 
			
		||||
#include "TrueTypeCharacter.hpp"
 | 
			
		||||
#include <ft2build.h>
 | 
			
		||||
#include FT_FREETYPE_H
 | 
			
		||||
 | 
			
		||||
namespace Dawn {
 | 
			
		||||
  class TrueTypeTexture final {
 | 
			
		||||
    public:
 | 
			
		||||
      FT_Face face;
 | 
			
		||||
      std::shared_ptr<Texture> texture;
 | 
			
		||||
      uint32_t fontSize;
 | 
			
		||||
      uint8_t style;
 | 
			
		||||
      std::unordered_map<wchar_t, struct TrueTypeCharacter> characterData;
 | 
			
		||||
 | 
			
		||||
      /**
 | 
			
		||||
       * Construct a new New True Type Face Texture object
 | 
			
		||||
       * 
 | 
			
		||||
       * @param face The freetype face object.
 | 
			
		||||
       * @param style Style that this font has, used for locking.
 | 
			
		||||
       */
 | 
			
		||||
      TrueTypeTexture(
 | 
			
		||||
        FT_Face face,
 | 
			
		||||
        uint32_t fontSize,
 | 
			
		||||
        uint8_t style
 | 
			
		||||
      );
 | 
			
		||||
 | 
			
		||||
      /**
 | 
			
		||||
       * Returns the character data for the given character.
 | 
			
		||||
       * 
 | 
			
		||||
       * @param c Character to get data for.
 | 
			
		||||
       * @return The Character data for the given character.
 | 
			
		||||
       */
 | 
			
		||||
      struct TrueTypeCharacter getCharacterData(wchar_t c);
 | 
			
		||||
 | 
			
		||||
      /**
 | 
			
		||||
       * Destroys this true type face texture.
 | 
			
		||||
       */
 | 
			
		||||
      ~TrueTypeTexture();
 | 
			
		||||
  };
 | 
			
		||||
}
 | 
			
		||||
@@ -7,4 +7,5 @@
 | 
			
		||||
target_sources(${DAWN_TARGET_NAME}
 | 
			
		||||
  PRIVATE
 | 
			
		||||
    CubeMesh.cpp
 | 
			
		||||
    QuadMesh.cpp
 | 
			
		||||
)
 | 
			
		||||
							
								
								
									
										39
									
								
								src/dawn/display/mesh/QuadMesh.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								src/dawn/display/mesh/QuadMesh.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,39 @@
 | 
			
		||||
// Copyright (c) 2023 Dominic Masters
 | 
			
		||||
// 
 | 
			
		||||
// This software is released under the MIT License.
 | 
			
		||||
// https://opensource.org/licenses/MIT
 | 
			
		||||
 | 
			
		||||
#include "QuadMesh.hpp"
 | 
			
		||||
 | 
			
		||||
using namespace Dawn;
 | 
			
		||||
 | 
			
		||||
void QuadMesh::buffer(
 | 
			
		||||
  const std::shared_ptr<Mesh> mesh,
 | 
			
		||||
  const glm::vec4 positions,
 | 
			
		||||
  const glm::vec4 coordinates,
 | 
			
		||||
  const int32_t verticeStart,
 | 
			
		||||
  const int32_t indiceStart
 | 
			
		||||
) {
 | 
			
		||||
  glm::vec3 vertices[QUAD_VERTICE_COUNT] = {
 | 
			
		||||
    glm::vec3(positions.x, positions.y, 0),
 | 
			
		||||
    glm::vec3(positions.z, positions.y, 0),
 | 
			
		||||
    glm::vec3(positions.x, positions.w, 0),
 | 
			
		||||
    glm::vec3(positions.z, positions.w, 0)
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  glm::vec2 coords[QUAD_VERTICE_COUNT] = {
 | 
			
		||||
    glm::vec2(coordinates.x, coordinates.y),
 | 
			
		||||
    glm::vec2(coordinates.z, coordinates.y),
 | 
			
		||||
    glm::vec2(coordinates.x, coordinates.w),
 | 
			
		||||
    glm::vec2(coordinates.z, coordinates.w)
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  int32_t indices[QUAD_INDICE_COUNT] = {
 | 
			
		||||
    verticeStart, verticeStart + 1, verticeStart + 3,
 | 
			
		||||
    verticeStart, verticeStart + 2, verticeStart + 3
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  mesh->bufferPositions(verticeStart, vertices, QUAD_VERTICE_COUNT);
 | 
			
		||||
  mesh->bufferCoordinates(verticeStart, coords, QUAD_VERTICE_COUNT);
 | 
			
		||||
  mesh->bufferIndices(indiceStart, indices, QUAD_INDICE_COUNT);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										32
									
								
								src/dawn/display/mesh/QuadMesh.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								src/dawn/display/mesh/QuadMesh.hpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,32 @@
 | 
			
		||||
// Copyright (c) 2023 Dominic Masters
 | 
			
		||||
// 
 | 
			
		||||
// This software is released under the MIT License.
 | 
			
		||||
// https://opensource.org/licenses/MIT
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
#include "display/mesh/Mesh.hpp"
 | 
			
		||||
 | 
			
		||||
#define QUAD_VERTICE_COUNT 4
 | 
			
		||||
#define QUAD_INDICE_COUNT 6
 | 
			
		||||
 | 
			
		||||
namespace Dawn {
 | 
			
		||||
  class QuadMesh {
 | 
			
		||||
    public:
 | 
			
		||||
      /**
 | 
			
		||||
       * Buffers quad mesh vertices and indices into the given mesh.
 | 
			
		||||
       * 
 | 
			
		||||
       * @param mesh The mesh to buffer into.
 | 
			
		||||
       * @param positions The positions of the vertices.
 | 
			
		||||
       * @param coordinates The coordinates of the vertices.
 | 
			
		||||
       * @param verticeStart The starting index of the vertices.
 | 
			
		||||
       * @param indiceStart The starting index of the indices.
 | 
			
		||||
       */
 | 
			
		||||
      static void buffer(
 | 
			
		||||
        const std::shared_ptr<Mesh> mesh,
 | 
			
		||||
        const glm::vec4 positions,
 | 
			
		||||
        const glm::vec4 coordinates,
 | 
			
		||||
        const int32_t verticeStart,
 | 
			
		||||
        const int32_t indiceStart
 | 
			
		||||
      );
 | 
			
		||||
  };
 | 
			
		||||
}
 | 
			
		||||
@@ -11,5 +11,4 @@ using namespace Dawn;
 | 
			
		||||
void SaveManager::init(std::shared_ptr<Game> game) {
 | 
			
		||||
  assertNotNull(game, "Game instance cannot be null!");
 | 
			
		||||
  this->game = game;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -6,15 +6,51 @@
 | 
			
		||||
#include "scene/SceneList.hpp"
 | 
			
		||||
#include "component/display/Camera.hpp"
 | 
			
		||||
#include "prefab/SimpleSpinningCube.hpp"
 | 
			
		||||
#include "display/font/TrueTypeTexture.hpp"
 | 
			
		||||
#include "component/display/material/SimpleTexturedMaterial.hpp"
 | 
			
		||||
#include "display/mesh/QuadMesh.hpp"
 | 
			
		||||
 | 
			
		||||
#include <ft2build.h>
 | 
			
		||||
#include FT_FREETYPE_H
 | 
			
		||||
 | 
			
		||||
using namespace Dawn;
 | 
			
		||||
 | 
			
		||||
FT_Library fontLibrary;
 | 
			
		||||
FT_Face face;
 | 
			
		||||
std::shared_ptr<TrueTypeTexture> texture;
 | 
			
		||||
 | 
			
		||||
void Dawn::helloWorldScene(Scene &s) {
 | 
			
		||||
  std::cout << "Hello World Scene" << std::endl;
 | 
			
		||||
  int32_t ret = FT_Init_FreeType(&fontLibrary);
 | 
			
		||||
  assertTrue(ret == 0, "Failed to initialize FreeType library");
 | 
			
		||||
  ret = FT_New_Face(fontLibrary,
 | 
			
		||||
    // "/usr/share/fonts/TTF/arial.ttf",
 | 
			
		||||
    "/home/yourwishes/Downloads/Noto_Sans_JP/static/NotoSansJP-Regular.ttf",
 | 
			
		||||
    0,
 | 
			
		||||
    &face
 | 
			
		||||
  );
 | 
			
		||||
  assertTrue(ret == 0, "Failed to load font face");
 | 
			
		||||
  texture = std::make_shared<TrueTypeTexture>(face, 128, 0);
 | 
			
		||||
 | 
			
		||||
  auto test = texture->getCharacterData(L'あ');
 | 
			
		||||
 | 
			
		||||
  auto cameraItem = s.createSceneItem();
 | 
			
		||||
  auto camera = cameraItem->addComponent<Camera>();
 | 
			
		||||
  cameraItem->lookAt({ 5, 5, 5 }, { 0, 0, 0 }, { 0, 1, 0 });
 | 
			
		||||
  // cameraItem->lookAt({ 5, 5, 5 }, { 0, 0, 0 }, { 0, 1, 0 });
 | 
			
		||||
  cameraItem->lookAt({ 0, 0, 3 }, { 0, 0, 0 }, { 0, 1, 0 });
 | 
			
		||||
 | 
			
		||||
  auto cubeItem = createSimpleSpinningCube(s);
 | 
			
		||||
  auto quad = s.createSceneItem();
 | 
			
		||||
  auto quadMesh = std::make_shared<Mesh>();
 | 
			
		||||
  quadMesh->createBuffers(QUAD_VERTICE_COUNT, QUAD_INDICE_COUNT);
 | 
			
		||||
  QuadMesh::buffer(
 | 
			
		||||
    quadMesh,
 | 
			
		||||
    glm::vec4(0, 0, test.size.x, test.size.y) / 128.0f,
 | 
			
		||||
    test.quad,
 | 
			
		||||
    0,
 | 
			
		||||
    0
 | 
			
		||||
  );
 | 
			
		||||
  auto quadRenderer = quad->addComponent<MeshRenderer>();
 | 
			
		||||
  quadRenderer->mesh = quadMesh;
 | 
			
		||||
 | 
			
		||||
  auto quadMaterial = quad->addComponent<SimpleTexturedMaterial>();
 | 
			
		||||
  quadMaterial->setTexture(texture->texture);
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user