Last active
December 12, 2015 09:28
-
-
Save Shaptic/4751252 to your computer and use it in GitHub Desktop.
Animation loading implementation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "Entity/Animation.hpp" | |
bool CAnimation::LoadFromFile(const std::string& filename, | |
gfx::CVertexBuffer& VBO) | |
{ | |
// Open the .icanim file. | |
std::ifstream anim(filename, std::ios::binary); | |
CAnimation::AnimationHeader& header = m_SheetDetails; | |
memset(&header, NULL, sizeof header); | |
if(!anim.is_open()) return false; | |
// Parse the header data. | |
anim >> header.width; | |
anim >> header.height; | |
anim >> header.columns; | |
anim >> header.rows; | |
// Bad header if it has any zeroes. | |
if(!(header.width && header.height && header.columns && header.rows)) | |
return false; | |
// Get file size. | |
const std::streampos begin = anim.tellg(); | |
anim.seekg(0, std::ios::end); | |
const std::streampos end = anim.tellg(); | |
anim.seekg(begin); | |
// Load raw texture data into a local buffer. | |
unsigned char* data = new unsigned char[end - begin]; | |
anim.read((char*)data, end - begin); | |
// Use GLFW to load a .tga file from raw pixel data. | |
// GLFW_NO_RESCALE_BIT is specified because modern OpenGL | |
// can deal with non-power-of-two textures. | |
GLFWimage img; | |
glfwReadMemoryImage(data, end - begin, &img, GLFW_NO_RESCALE_BIT); | |
// Small shortcut. | |
uint16_t w = img.Width; // or header.width | |
uint16_t h = img.Height; // or header.height | |
// Individual sprite width. | |
uint16_t sprite_w = w / header.columns; | |
uint16_t sprite_h = h / header.rows; | |
vertex2_t quad_v[4]; | |
uint16_t quad_i[6] = {0, 1, 3, 3, 2, 1}; | |
// This gives the texture coordinates necessary to render a | |
// single sprite in the sheet. For example, in a 2x2 sheet of | |
// 32x32 sprites, this would give the vector <0.5, 0.5>, meaning | |
// that each sprite is half the width and half the height of the | |
// entire sprite sheet, which is true. | |
m_TexcDim = math::vector2_t(1.f / header.columns, 1.f / header.rows); | |
// Mesh coordinates for the quad. | |
quad_v[0].Position = math::vector2_t(0, 0); | |
quad_v[1].Position = math::vector2_t(sprite_w, 0); | |
quad_v[2].Position = math::vector2_t(sprite_w, sprite_h); | |
quad_v[3].Position = math::vector2_t(0, sprite_h); | |
// Texture coordinates are for the entire sprite sheet. | |
// Later, these are used to calculate the offset within | |
// the shader. See Animate.fs for more detail. | |
quad_v[0].TexCoord = math::vector2_t(0.f, 1.f); | |
quad_v[1].TexCoord = math::vector2_t(1.f, 1.f); | |
quad_v[2].TexCoord = math::vector2_t(1.f, 0.f); | |
quad_v[3].TexCoord = math::vector2_t(0.f, 0.f); | |
asset::CTexture* pTexture = asset::CAssetManager::Create<asset::CTexture>(); | |
pTexture->SetFilename(filename); | |
pTexture->LoadFromRaw(img.Format, img.Format, w, h, img.Data); | |
header.pTexture = pTexture; | |
glfwFreeImage(&img); | |
// Load quad mesh | |
m_Mesh.LoadMesh(quad_v, 4, quad_i, 6); | |
// Load whole sprite sheet into surface. | |
m_Mesh.GetSurfaces()[0]->pMaterial->pTexture = pTexture; | |
// Load the rendering shader. | |
gfx::CShaderPair* pShader = m_Mesh.GetSurfaces()[0]->pMaterial->pShader; | |
if(pShader == NULL) | |
{ | |
pShader = new gfx::CShaderPair; | |
if(!pShader->LoadFromFile("Shaders/Default.vs", "Shaders/Animate.fs")) | |
return false; | |
} | |
// The shader contains an offset so that the texture coordinates | |
// can be shifted to reflect the current sprite. | |
pShader->Bind(); | |
m_tc_loc = pShader->GetUniformLocation("tc_offset"); | |
m_tc_str = pShader->GetUniformLocation("tc_start"); | |
glUniform2f(m_tc_loc, m_TexcDim.x, m_TexcDim.y); | |
glUniform2f(m_tc_str, 0.f, 0.f); // We want the top-left sprite | |
pShader->Unbind(); | |
// Assign the shader to the mesh | |
m_Mesh.GetSurfaces()[0]->pMaterial->pShader = pShader; | |
// Rigid body collision should be to a single sprite. | |
m_CollisionBox.w = m_SheetDetails.width / m_SheetDetails.columns; | |
m_CollisionBox.h = m_SheetDetails.height / m_SheetDetails.rows; | |
// Load the quad into the VBO and return the result. | |
return m_Mesh.LoadIntoVBO(VBO); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment