mirror of
https://github.com/libretro/Play-.git
synced 2024-12-04 15:26:23 +00:00
179 lines
4.1 KiB
C++
179 lines
4.1 KiB
C++
#include "IconMesh.h"
|
|
#include <gl/glew.h>
|
|
#include <math.h>
|
|
|
|
CIconMesh::CIconMesh(const IconPtr& icon)
|
|
: m_icon(icon)
|
|
, m_time(0)
|
|
, m_texture(0)
|
|
, m_animLength(0)
|
|
{
|
|
m_frameInfluences.reserve(m_icon->GetFrameCount());
|
|
|
|
//Compute animation length
|
|
for(unsigned int i = 0; i < m_icon->GetFrameCount(); i++)
|
|
{
|
|
const CIcon::FRAME* frame = m_icon->GetFrame(i);
|
|
for(unsigned int j = 0; j < frame->nKeyCount; j++)
|
|
{
|
|
const CIcon::KEY& key = frame->pKeys[j];
|
|
m_animLength = std::max<float>(m_animLength, key.nTime);
|
|
}
|
|
}
|
|
|
|
LoadTexture();
|
|
ComputeFrameInfluences();
|
|
}
|
|
|
|
CIconMesh::~CIconMesh()
|
|
{
|
|
glDeleteTextures(1, &m_texture);
|
|
}
|
|
|
|
void CIconMesh::Render() const
|
|
{
|
|
const CIcon::TEXCOORD* pTexCoords = m_icon->GetTexCoords();
|
|
unsigned int nVertexCount = m_icon->GetVertexCount();
|
|
|
|
glBindTexture(GL_TEXTURE_2D, m_texture);
|
|
|
|
glBegin(GL_TRIANGLES);
|
|
|
|
for(unsigned int i = 0; i < nVertexCount; i++)
|
|
{
|
|
glTexCoord2f(pTexCoords[i].nS, pTexCoords[i].nT);
|
|
|
|
float totalX = 0;
|
|
float totalY = 0;
|
|
float totalZ = 0;
|
|
|
|
for(unsigned int j = 0; j < m_frameInfluences.size(); j++)
|
|
{
|
|
const auto& influence(m_frameInfluences[j]);
|
|
auto shape = m_icon->GetShape(influence.shapeId);
|
|
if(!shape) continue;
|
|
totalX += shape[i].nX * influence.amplitude;
|
|
totalY += shape[i].nY * influence.amplitude;
|
|
totalZ += shape[i].nZ * influence.amplitude;
|
|
}
|
|
|
|
glVertex3f(totalX, totalY, totalZ);
|
|
}
|
|
|
|
glEnd();
|
|
|
|
glBindTexture(GL_TEXTURE_2D, NULL);
|
|
}
|
|
|
|
void CIconMesh::Update(float dt)
|
|
{
|
|
ComputeFrameInfluences();
|
|
|
|
m_time += (dt * 133);
|
|
if(m_time > m_animLength)
|
|
{
|
|
m_time -= m_animLength;
|
|
}
|
|
}
|
|
|
|
void CIconMesh::ComputeFrameInfluences()
|
|
{
|
|
m_frameInfluences.resize(0);
|
|
|
|
for(unsigned int i = 0; i < m_icon->GetFrameCount(); i++)
|
|
{
|
|
//We need to check if this frame influences the mesh at the current time
|
|
|
|
const CIcon::FRAME* frame = m_icon->GetFrame(i);
|
|
float frameAmp = 0;
|
|
|
|
for(unsigned int j = 0; j < frame->nKeyCount; j++)
|
|
{
|
|
const CIcon::KEY& key = frame->pKeys[j];
|
|
//Check end and start cases
|
|
if(
|
|
((j == 0) && m_time <= key.nTime) ||
|
|
((j == frame->nKeyCount - 1))
|
|
)
|
|
{
|
|
frameAmp = key.nAmplitude;
|
|
break;
|
|
}
|
|
|
|
assert((j + 1) != frame->nKeyCount);
|
|
const CIcon::KEY& key0 = frame->pKeys[j + 0];
|
|
const CIcon::KEY& key1 = frame->pKeys[j + 1];
|
|
|
|
if(m_time >= key0.nTime && m_time <= key1.nTime)
|
|
{
|
|
float insideTime = m_time - key0.nTime;
|
|
float slope = (key1.nAmplitude - key0.nAmplitude) / (key1.nTime - key0.nTime);
|
|
frameAmp = (insideTime * slope) + key0.nAmplitude;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(frameAmp != 0)
|
|
{
|
|
//GTA San Andreas' icon references an invalid shape id.
|
|
//If it's invalid, reference the first shape
|
|
uint32 shapeId = frame->nShapeId;
|
|
if(shapeId >= m_icon->GetShapeCount()) shapeId = 0;
|
|
|
|
FRAMEINFLUENCE influence;
|
|
influence.shapeId = shapeId;
|
|
influence.amplitude = frameAmp;
|
|
m_frameInfluences.push_back(influence);
|
|
}
|
|
}
|
|
|
|
if(
|
|
(m_frameInfluences.size() == 0) &&
|
|
(m_icon->GetFrameCount() == 1))
|
|
{
|
|
const CIcon::FRAME* frame = m_icon->GetFrame(0);
|
|
|
|
FRAMEINFLUENCE influence;
|
|
influence.shapeId = frame->nShapeId;
|
|
influence.amplitude = 1;
|
|
m_frameInfluences.push_back(influence);
|
|
}
|
|
}
|
|
|
|
void CIconMesh::LoadTexture()
|
|
{
|
|
uint32* pCvtBuffer = new uint32[128 * 128];
|
|
const uint16* pTexture = m_icon->GetTexture();
|
|
|
|
for(unsigned int i = 0; i < (128 * 128); i++)
|
|
{
|
|
uint16 nPixel = pTexture[i];
|
|
|
|
uint8 nR = ((nPixel & 0x001F) >> 0) << 3;
|
|
uint8 nG = ((nPixel & 0x03E0) >> 5) << 3;
|
|
uint8 nB = ((nPixel & 0x7C00) >> 10) << 3;
|
|
uint8 nA = (nPixel & 0x8000) != 0 ? 0xFF : 0x00;
|
|
|
|
((uint8*)&pCvtBuffer[i])[0] = nR;
|
|
((uint8*)&pCvtBuffer[i])[1] = nG;
|
|
((uint8*)&pCvtBuffer[i])[2] = nB;
|
|
((uint8*)&pCvtBuffer[i])[3] = nA;
|
|
}
|
|
|
|
glGenTextures(1, &m_texture);
|
|
|
|
glBindTexture(GL_TEXTURE_2D, m_texture);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
|
|
|
|
glTexImage2D(GL_TEXTURE_2D, 0, 4, 128, 128, 0, GL_RGBA, GL_UNSIGNED_BYTE, pCvtBuffer);
|
|
|
|
glBindTexture(GL_TEXTURE_2D, NULL);
|
|
|
|
delete [] pCvtBuffer;
|
|
}
|