Jump to content
  • Advertisement

assboot

Member
  • Content Count

    11
  • Joined

  • Last visited

Community Reputation

0 Neutral

About assboot

  • Rank
    Member

Personal Information

  • Interests
    Programming

Recent Profile Visitors

The recent visitors block is disabled and is not being shown to other users.

  1. Hi, I'm trying to set up my visual studio code environment for my c++ project that I compile with gcc. The makefiles are made with premake. A problem I have is that predefined macros and things from the precompiled header are not detected by vs code which means I get incorrect highlighting and intellisense errors. How do I let vs code know about these things so it can get properly highlighted?
  2. Thank you for stopping me from discovering that the hard way I'm using Lua 5.3.5 I'm trying to completely clear the stack after each update() call, yet the problem persists. Also I found out that it doesn't seem to have anything to do with my __index function, as this happens whenever I create a new table in update(). I've now implemented the Free() function for my memory management, it still doesn't manage to catch up with all the allocation for the tables. I'm guessing the lua gc is just too slow to collect that many tables, but it seems like such a loss to not be able to create tables for such simple tasks in update(). Doesn't seem like I can edit the post anymore (I'm new to this site), so I'll just dump the new code for the memory manager here. struct LuaMemPool { const void *begin; const void *end; ubyte *current; static constexpr u8 ALIGNMENT = 8; static constexpr u8 MIN_BLOCK_SIZE = ALIGNMENT * 8; struct FreeList { FreeList *next; } *freelistHead; LuaMemPool(void *begin, void *end) : begin(begin), end(end), freelistHead(nullptr), current((ubyte*)begin) { } void Reset() { freelistHead = nullptr; current = (ubyte*)begin; } void Free(void *ptr, size_t size) { size = SizeToAllocate(size); if (size >= MIN_BLOCK_SIZE) { FreeList *_newHead = (FreeList*)ptr; _newHead->next = freelistHead; freelistHead = _newHead; } else { } } size_t SizeToAllocate(size_t size) { if (size < MIN_BLOCK_SIZE) { size = MIN_BLOCK_SIZE; } return size; } void *Allocate(size_t sizeBytes) { sizeBytes = SizeToAllocate(sizeBytes); if (sizeBytes <= MIN_BLOCK_SIZE && freelistHead) { // Allocate from freed memory void *_ptr = freelistHead; freelistHead = freelistHead->next; return _ptr; } else { current = (ubyte*)(((uintptr_t)current + (ALIGNMENT - 1)) & ~(ALIGNMENT - 1)); void *_ptr = current; current += sizeBytes; WZ_ASSERT(current <= end, "Memory usage overflow"); return _ptr; } } void *Realloc(void *ptr, size_t oldSize, size_t newSize) { size_t _toCopy = oldSize < newSize ? oldSize : newSize; void *_newPtr = Allocate(newSize); memcpy(_newPtr, ptr, _toCopy); Free(ptr, oldSize); return _newPtr; } int32 Allocated() { return (int32)(current - (ubyte*)begin); } static void *Alloc(void *ud, void *ptr, size_t osize, size_t nsize) { LuaMemPool& _pool = *((LuaMemPool*)ud); if (nsize == 0) { if (ptr != nullptr && osize != 0) { _pool.Free(ptr, osize); } return NULL; } else { if (ptr == nullptr) { return _pool.Allocate(nsize); } return _pool.Realloc(ptr, osize, nsize); } } };
  3. I've recently implemented runtime lua scripting in my game engine, and am currently just polishing it. During the polishing I noticed that when I do this one specific thing in lua, the stack gets overflown. I'm doing the memory management my self for the lua stack, and I'll code dump it at the bottom of this post in case it has any relevance. To give some context, I'm using the __index and __newindex metamethods for reading and writing fields in the user data "LuaEntity", which is basically just a wrapper for the Entity class in my engine. This is somewhat what the __index and __newindex functions look like in C++ static int32 __index(lua_State *ls) { string _index = lua_tostring(ls, -1); if (lua_isuserdata(ls, -2) && !lua_isnil(ls, -2)) { auto _entity = (LuaEntity*)lua_touserdata(ls, -2); if (SceneManagement::GetEntity(_entity->id)) { _entity->UpdateProps(); if (_index == "x") { lua_pushnumber(ls, _entity->x); } else if (_index == "some_field") { lua_pushnumber(ls, _entity->some_field); } else if (_index == "some_other_field") { lua_pushnumber(ls, _entity->some_other_field); } else /* if reading a non-default field */ { lua_getuservalue(ls, -2); WZ_ASSERT(!lua_isnil(ls, -1), "Tried reading unitialized field '" + _index + "' in '" + _entity->name + "'"); lua_pushvalue(ls, -2); lua_gettable(ls, -2); lua_remove(ls, -2); } return 1; } } else { lua_pushnil(ls); } return 1; } static int32 __newindex(lua_State *ls) { string _index = lua_tostring(ls, -2); if (lua_isuserdata(ls, -3) && !lua_isnil(ls, -3)) { auto _entity = (LuaEntity*)lua_touserdata(ls, -3); if (SceneManagement::GetEntity(_entity->id)) { if (_index == "x") { WZ_ASSERT(lua_isnumber(ls, -1), "Expected number value"); // .. Set "x" to the value top on stack } else if (_index == "some_field") { WZ_ASSERT(lua_isnumber(ls, -1), "Expected number value"); // .. Set "some_field" to the value top on stack } else if (_index == "some_other_field") { WZ_ASSERT(lua_isnumber(ls, -1), "Expected number value"); // .. Set "some_other_field" to the value top on stack } else /* if writing a non-default field */ { lua_getuservalue(ls, -3); lua_pushvalue(ls, -3); lua_pushvalue(ls, -3); lua_settable(ls, -3); lua_remove(ls, -1); } _entity->UpdateProps(); } } return 0; } }; This all works fine as in I can read and write both the default but also user-made fields in the entity table without a problem like this: local function update() -- A callback function that's invoked each frame from C++ local entity = entity_get("some_entity") local old_x = entity.x local old_y = entity.y -- .. do stuff if (old_x ~= entity.x or old_y ~= entity.y) then -- .. entity moved end end This keeps the memory steady with no problems, however, If I were to do the same thing but instead of storing entity position in old_x and old_y I would store it in a table called old_pos like this: local function update() -- A callback function that's invoked each frame from C++ local entity = entity_get("some_entity") local old_pos = { x = entity.x, y = entity.y } -- return values 'x' and 'y', pushed to the stack in C++, doesn't get garbage collected - memory fills up -- .. do stuff if (old_pos.x ~= entity.x or old_pos.y ~= entity.y) then -- .. entity moved end end then the values x and y, each pushed to the stack in __index as a return value, seems to not get garbage collected by lua which quickly fills up my stack budget and causes the stack to overflow. Here is how I've told lua to handle stack memory: struct LuaMemPool { const void *head; const void *tail; const ubyte *headByte; ubyte *current; LuaMemPool(void *head, void *tail) : head(head), tail(tail), current((ubyte*)head), headByte((ubyte*)head) { } void Free(void */*ptr*/) { } void *Allocate(size_t sizeBytes) { void *_ptr = current; current += sizeBytes; WZ_ASSERT(current <= tail, "Memory usage overflow"); return _ptr; } void *Realloc(void *ptr, size_t oldSize, size_t newSize) { void *_newPtr = Allocate(newSize); memcpy(_newPtr, ptr, oldSize); Free(ptr); return _newPtr; } int32 Allocated() { return (int32)(current - headByte); } static void *Alloc(void *ud, void *ptr, size_t osize, size_t nsize) { LuaMemPool& _pool = *((LuaMemPool*)ud); if (nsize == 0) { if (ptr != nullptr) { _pool.Free(ptr); } return NULL; } else { if (ptr == nullptr) { return _pool.Allocate(nsize); } return _pool.Realloc(ptr, osize, nsize); } } }; I am aware that I'm not freeing memory.
  4. I used to load glyphs and create a texture for each one with Freetype, but this is very costly so I decided that I need to combine all textures into one and draw the part that represents a given glyph. However when I try this, all glyph textures are just black in the game. Kerning, placement and size is perfectly fine but the textures are just black boxes. This is how I initialize a font after successfully loading it with freetype: bool Font::Init() { auto _error = FT_Set_Pixel_Sizes(m_face, 0, m_fontSize); if (_error != FT_Err_Ok) { WZ_ERROR("An error occured when setting pixel sizes for font '{0}'. Error: '{1}'.", m_face->family_name, GetErrorMessage(_error)); return false; } m_bitmap = new Texture2D(m_face->glyph->bitmap.width, m_face->glyph->bitmap.rows, std::vector<unsigned char>(), GL_RED, GL_RED); m_bitmap->Bind(); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); WZ_TRACE("Loading glyphs..."); unsigned int _fails = 0; int _previousIndex = 0; float _width = 0; bool _hasKerning = FT_HAS_KERNING(m_face); WZ_TRACE("Detected kerning..."); for (GLubyte c = 33; c < 127; c++) { _error = FT_Load_Char(m_face, c, FT_LOAD_RENDER); if (_error != FT_Err_Ok) { WZ_ERROR("Failed to load glyph '{0}' with font {1}", (char)c, m_face->family_name); _fails++; continue; } auto _glyphIndex = FT_Get_Char_Index(m_face, c); vec2 _kerning(0, 0); if (_hasKerning && _previousIndex && _glyphIndex) { FT_Vector _delta; FT_Get_Kerning(m_face, _previousIndex, _glyphIndex, FT_KERNING_DEFAULT, &_delta); _kerning = vec2(_delta.x, _delta.y); } unsigned int _len = m_face->glyph->bitmap.width * m_face->glyph->bitmap.rows; if (_len <= 0) { WZ_WARN("Could find data to create a texture for '{0}' from font '{1}'.", (char)c, m_face->family_name); _fails++; continue; } m_glyphs[c] = { _kerning, vec2(m_face->glyph->bitmap_left, m_face->glyph->bitmap_top), maths::Rect(_width, 0, m_face->glyph->bitmap.width, m_face->glyph->bitmap.rows), m_face->glyph->advance.x }; glTextureSubImage2D( GL_TEXTURE_2D, 0, m_glyphs[c].source.x, m_glyphs[c].source.y, m_glyphs[c].source.w, m_glyphs[c].source.h, GL_RED, GL_RED, m_face->glyph->bitmap.buffer ); _width += m_face->glyph->bitmap.width; _previousIndex = _glyphIndex; } m_bitmap->Unbind(); WZ_INFO("Successfully loaded glyphs."); if (_fails > 0) { WZ_WARN("Failed to load {0}/127 glyphs.", _fails); } return true; } This is what happens in Texture2D: inline Texture2D(unsigned int width, unsigned int height, std::vector<unsigned char> rawData, GLint internalFormat = GL_RGBA8, GLenum format = GL_RGBA) : Resource("") { m_width = width; m_height = height; m_rawData = rawData; m_internalFormat = internalFormat; m_format = format; m_isFileBound = false; m_isTexture = true; Init(); m_isEmpty = false; } void Texture2D::Init() { m_buffer = m_rawData.size(); unsigned char *_dataArr; if (m_rawData.size() > 0) { _dataArr = &m_rawData[0]; } else { _dataArr = 0; } GLFunc(glGenTextures(1, &m_ID)); Bind(); GLFunc(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); GLFunc(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)); GLFunc(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)); GLFunc(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)); GLFunc(glTexImage2D(GL_TEXTURE_2D, 0, m_internalFormat, m_width, m_height, 0, m_format, GL_UNSIGNED_BYTE, _dataArr)); Unbind(); } void Texture2D::Bind() { GLFunc(glActiveTexture(GL_TEXTURE0)); GLFunc(glBindTexture(GL_TEXTURE_2D, m_ID)); } void Texture2D::Unbind() { GLFunc(glBindTexture(GL_TEXTURE_2D, 0)); } And here is how I render stuff with a batch renderer: void BatchRenderer2D::SubmitString(std::string text, Font * font, const vec3 pos, float spacing, float lineSpacing, const vec3 origin, const vec3 scale, const vec3 rotation, const Color color) { vec3 _off(0, 0, 0); float _tallest = 0; float _averageWidth = 0; float _widthSum = 0; float _count = 0; for (char c : text) { if (c == '\n') { _off.x = 0; _off.y -= (lineSpacing + _tallest) * scale.y; _tallest = 0; } if (c > 31 && c < 127) { if (c == 32) { _off.x += _averageWidth * scale.x; } else { auto _height = font->MeasureString(std::string(1, c), spacing, lineSpacing).y; if (_height > _tallest) { _tallest = _height; } auto _glyph = font->GetGlyph(c); _widthSum += _glyph.source.w; _count++; _averageWidth = _widthSum / _count; auto _kerning = vec3(_glyph.kerning.x, _glyph.kerning.y, 0) * scale; auto _bearing = vec3(_glyph.bearing.x, -(_glyph.source.h - _glyph.bearing.y), 0) * scale; auto _drawPos = pos + _off + _kerning + _bearing; m_submittingText = true; Submit(font->GetBitmap(), _drawPos, _glyph.source, origin, scale, rotation, color); _off.x += (_glyph.advance >> 6) * scale.x + spacing; } } } } void BatchRenderer2D::Submit(Drawable2D * toDraw, const vec3 pos, Rect source, const vec3 origin, const vec3 scale, const vec3 rotation, const Color color) { if (!m_isReady) { WZ_ERROR("Tried to submit to a renderer before calling Begin(). Please call renderer.Begin() before submitting."); return; } int _tid = toDraw->GetID(); float _textureSlot = -1; if (_tid > 0) { bool _found = false; for (int i = 0; i < m_textureSlots.size(); i++) { if (m_textureSlots[i] == _tid) { _textureSlot = (float)(i); _found = true; break; } } if (!_found) { if (m_textureSlots.size() >= RENDERER_MAX_TEXTURE_BINDS) { int _sCount = m_submissionCount; End(); Flush(); if (m_transformMode == TRANSFORM_MODE_CALCULATED) { Begin(m_camTransform); } else if (m_transformMode == TRANSFORM_MODE_UNCALCULATED) { Begin(m_camPos); } m_submissionCount = _sCount; } m_textureSlots.push_back(_tid); _textureSlot = (float)m_textureSlots.size() - 1; } } vec3 _texSize = vec3(toDraw->GetWidth(), toDraw->GetHeight(), 1.f); vec3 _quadSize = vec3(source.w, source.h, 0); float _rot = -rotation.z; float _cosR = _rot != 0 ? cos(_rot) : 0; float _sinR = _rot != 0 ? sin(_rot) : 0; vec2 _texCoords[] = { vec2(source.Left() / _texSize.x, source.Top() / _texSize.y), vec2(source.Right() / _texSize.x, source.Top() / _texSize.y), vec2(source.Right() / _texSize.x, source.Bottom() / _texSize.y), vec2(source.Left() / _texSize.x, source.Bottom() / _texSize.y) }; //Top left vec3 _offset = vec3(0, source.h, 0) - origin; if (_rot != 0) { _offset = vec3(_offset.x * _cosR - _offset.y * _sinR, _offset.x * _sinR + _offset.y * _cosR, 0); } m_buffer->position = pos + _offset * scale; m_buffer->color = color; m_buffer->texCoord = _texCoords[0]; m_buffer->tid = _textureSlot; m_buffer->isText = (int)m_submittingText; m_buffer++; //Top right _offset = vec3(source.w, source.h, 0) - origin; if (_rot != 0) { _offset = vec3(_offset.x * _cosR - _offset.y * _sinR, _offset.x * _sinR + _offset.y * _cosR, 0); } m_buffer->position = pos + _offset * scale; m_buffer->color = color; m_buffer->texCoord = _texCoords[1]; m_buffer->tid = _textureSlot; m_buffer->isText = (int)m_submittingText; m_buffer++; //Bottom right _offset = vec3(source.w, 0, 0) - origin; if (_rot != 0) { _offset = vec3(_offset.x * _cosR - _offset.y * _sinR, _offset.x * _sinR + _offset.y * _cosR, 0); } m_buffer->position = pos + _offset * scale; m_buffer->color = color; m_buffer->texCoord = _texCoords[2]; m_buffer->tid = _textureSlot; m_buffer->isText = (int)m_submittingText; m_buffer++; //Bottom left _offset = vec3(0, 0, 0) - origin; if (_rot != 0) { _offset = vec3(_offset.x * _cosR - _offset.y * _sinR, _offset.x * _sinR + _offset.y * _cosR, 0); } m_buffer->position = pos + _offset * scale; m_buffer->color = color; m_buffer->texCoord = _texCoords[3]; m_buffer->tid = _textureSlot; m_buffer->isText = (int)m_submittingText; m_buffer++; m_submissionCount++; m_indexCount += 6; m_submittingText = false; } void BatchRenderer2D::Begin(const mat4 camTransform) { m_transformMode = TRANSFORM_MODE_CALCULATED; m_camTransform = camTransform; GLFunc(glBindBuffer(GL_ARRAY_BUFFER, m_VBOIndex)); GLFunc(m_buffer = (VertexData*)glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY)); m_isReady = true; } void BatchRenderer2D::End() { GLFunc(glUnmapBuffer(GL_ARRAY_BUFFER)); //GLFunc(glBindBuffer(GL_ARRAY_BUFFER, 0)); m_isReady = false; } void BatchRenderer2D::Flush() { for (size_t i = 0; i < m_textureSlots.size(); i++) { GLFunc(glActiveTexture(GL_TEXTURE0 + i)); GLFunc(glBindTexture(GL_TEXTURE_2D, m_textureSlots[i])); } GLFunc(glBindVertexArray(m_VAOIndex)); m_IBO->Bind(); if (m_transformMode == TRANSFORM_MODE_CALCULATED) { Shader::Tex2DShader()->SetUniformMat4("pr_matrix", m_proj * m_camTransform); } else if (m_transformMode == TRANSFORM_MODE_UNCALCULATED) { Shader::Tex2DShader()->SetUniformMat4("pr_matrix", m_proj * glm::inverse(glm::translate(glm::identity<mat4>(), m_camPos))); } GLFunc(glDrawElements(GL_TRIANGLES, m_indexCount, GL_UNSIGNED_INT, NULL)); m_textureSlots.clear(); m_submissionCount = 0; m_indexCount = 0; } And here are the shaders: Vertex: #version 410 core layout (location = 0) in vec4 position; layout (location = 1) in vec4 color; layout (location = 2) in vec2 texCoord; layout (location = 3) in float texID; layout (location = 4) in float isText; uniform mat4 pr_matrix; out DATA{ vec4 pos; vec4 col; vec2 texCoord; float texID; float isText; } vs_out; void main(){ gl_Position = pr_matrix * position; vs_out.pos = position; vs_out.col = color; vs_out.texCoord = texCoord; vs_out.texID = texID; vs_out.isText = isText; } Fragment: #version 410 core out vec4 color; in DATA{ vec4 pos; vec4 col; vec2 texCoord; float texID; float isText; } fs_in; uniform sampler2D textures[32]; void main(){ color = fs_in.col; if (fs_in.texID >= 0) { int texID = int(fs_in.texID - 0.5); color = texture2D(textures[int(fs_in.texID)], vec2(fs_in.texCoord.s, 1.0 - fs_in.texCoord.t)) * fs_in.col; } } Sorry for the big code dump im really bad on formulating posts for questions I have.
  5. assboot

    Is my 4x4 matrix math correct?

    I'll actually just go to sleep now and try to fix this tomorrow. Merry Christmas by the way haha.
  6. assboot

    Is my 4x4 matrix math correct?

    I just realized I just renamed rows to columns but then made the Transform() function calculate it row-wise. It's 1:42 AM here. Anyways, my translate function is the same as your translate function. Am I not actually doing any of the math wrongs in my code then? (I just renamed rows to columns and went with the original Transform() function).
  7. assboot

    Is my 4x4 matrix math correct?

    Haha you again, thanks for the help. But I suppose it's the Transform() function I need to change then? I'm currently trying this instead return vec3( transform->columns[0].x * x + transform->columns[1].x * y + transform->columns[2].x * z + transform->columns[3].x, transform->columns[0].y * x + transform->columns[1].y * y + transform->columns[1].y * z + transform->columns[3].y, transform->columns[0].z * x + transform->columns[1].z * y + transform->columns[2].z * z + transform->columns[3].z ); But that doesn't seem to be correct as I don't get the result I want, am I doing the math right? Good thing I'm taking a linear algebra class next term haha.
  8. I'm trying to set the correct world positions in 4 vertices and for reasons I need to do the calculations with matrices on the CPU before I send in the positions in my GLSL shader. I decide the positions somewhat like this mat4 m_proj; void Submit(renderable, vec3 pos, vec3 origin, vec3 scale) { vec3 _size = renderable.size; vec3 _pos = pos + origin + vec3(0, _size.y, 0); mat4 _model = mat4::CreateScale(scale) * mat4::Translate(_pos); mat4 _pm = m_proj * _model; _pos = _pm.Transform(_pos); vertex1.pos = _pos; _pos = pos + origin + vec3(_size.x, _size.y, 0); _model = mat4::CreateScale(scale) * mat4::Translate(_pos); _pm = m_proj * _model; _pos = _pm.Transform(_pos); vertex2.pos = _pos; _pos = pos + origin + vec3(_size.x, 0, 0); _model = mat4::CreateScale(scale) * mat4::Translate(_pos); _pm = m_proj * _model; _pos = _pm.Transform(_pos); vertex3.pos = _pos; _pos = pos + origin; _model = mat4::CreateScale(scale) * mat4::Translate(_pos); _pm = m_proj * _model; _pos = _pm.Transform(_pos); vertex4.pos = _pos; //Code to submit... } And here are all the used mat4 functions: union { float elements[16]; vec4 rows[4]; }; mat4 Multiply(mat4 other) { //This is used in * operator float _data[16]; for (int _row = 0; _row < 4; _row++) { for (int _col = 0; _col < 4; _col++) { float _sum = 0.0f; for (int e = 0; e < 4; e++) { _sum += elements[e + _row * 4] * other.elements[_col + e * 4]; } _data[_col + _row * 4] = _sum; } } memcpy(elements, _data, 4 * 4 * sizeof(float)); return *this; } mat4 CreateScale(vec3 scale) { mat4 _result(1.0f); //Identity matrix _result.elements[0 + 0 * 4] = scale.x; _result.elements[1 + 1 * 4] = scale.y; _result.elements[2 + 2 * 4] = scale.z; return _result; } mat4 Translate(vec3 pos) { mat4 _result(1.f); _result.elements[0 + 3 * 4] = translation.x; _result.elements[1 + 3 * 4] = translation.y; _result.elements[2 + 3 * 4] = translation.z; return _result; } vec3 Transform(vec3 vec) { return vec3( rows[0].x * vec.x + rows[0].y * vec.y + rows[0].z * vec.z + rows[0].w, rows[1].x * vec.x + rows[1].y * vec.y + rows[1].z * vec.z + rows[1].w, rows[2].x * vec.x + rows[2].y * vec.y + rows[2].z * vec.z + rows[2].w ); } m_proj is just an orthographic matrix which I know is fine. My question is really just if there is something wrong with what I'm doing here as I don't get the result I want.
  9. Yup building the .lib file with /MD seems to fix my issues. Thanks a lot. For future googlers: In the freetype solution you need to go to project properties -> C/C++ -> Code Generation and change "Runtime Library" from 'Multi-threaded (/MT)' to 'Multi-threaded DLL (/MD)' and just build it again and remember to grab the new freetype.lib file and replace the one that's linked to your project.
  10. I've downloaded the latest version of freetype, added freetype.lib and the include folder to my project and linked everything in project properties. Is there something I'm missing? I'm getting 7 unresolved externals: Error LNK2019 unresolved external symbol __imp_FT_Stream_OpenLZW referenced in function PCF_Face_Init Wizzy-core C:\Users\CM\Documents\SourceTree\Wizzy\WizzyEngine\Wizzy-core\freetype.lib(pcf.obj) 1 Error LNK2019 unresolved external symbol __imp_FT_Bitmap_Convert referenced in function tt_face_load_sbit_image Wizzy-core C:\Users\CM\Documents\SourceTree\Wizzy\WizzyEngine\Wizzy-core\freetype.lib(sfnt.obj) 1 Error LNK2019 unresolved external symbol __imp_FT_Bitmap_Done referenced in function tt_face_load_sbit_image Wizzy-core C:\Users\CM\Documents\SourceTree\Wizzy\WizzyEngine\Wizzy-core\freetype.lib(sfnt.obj) 1 Error LNK2019 unresolved external symbol __imp_FT_Bitmap_Init referenced in function tt_face_load_sbit_image Wizzy-core C:\Users\CM\Documents\SourceTree\Wizzy\WizzyEngine\Wizzy-core\freetype.lib(sfnt.obj) 1 Error LNK2019 unresolved external symbol __imp_FT_Get_Font_Format referenced in function FT_Load_Glyph Wizzy-core C:\Users\CM\Documents\SourceTree\Wizzy\WizzyEngine\Wizzy-core\freetype.lib(ftbase.obj) 1 Error LNK2019 unresolved external symbol __imp_FT_Gzip_Uncompress referenced in function woff_open_font Wizzy-core C:\Users\CM\Documents\SourceTree\Wizzy\WizzyEngine\Wizzy-core\freetype.lib(sfnt.obj) 1 Error LNK2019 unresolved external symbol __imp_FT_Stream_OpenGzip referenced in function PCF_Face_Init Wizzy-core C:\Users\CM\Documents\SourceTree\Wizzy\WizzyEngine\Wizzy-core\freetype.lib(pcf.obj) 1 EDIT: It actually builds fine until I call FT_Init_FreeType() This is all the code that's related to FreeType /******fonthandler.h******/ #pragma once #include <ft2build.h> #include FT_FREETYPE_H class FontHandler { private: FT_Library m_lib; private: FontHandler() {} public: bool Init(); }; /******fonthandler.cpp******/ #include "fonthandler.h" #include "..\..\..\debug\debugging.h" bool FontHandler::Init() { auto _error = FT_Init_FreeType(&m_lib); if (_error) { log("Failed to initialize FreeType..."); log("Error: '{0}'", _error); } return !_error; }
  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!