Improved keyframe mesh interface
Also improved animation performance by using a discard-and-write lock when interpoling. Former-commit-id: 277b5ad8f148ab73b99edf83cf8c6e5d0e6dfc82
This commit is contained in:
parent
82d6438ec3
commit
cc45746799
|
|
@ -30,7 +30,7 @@ class NAZARA_API NzKeyframeMesh final : public NzSubMesh
|
||||||
nzAnimationType GetAnimationType() const override;
|
nzAnimationType GetAnimationType() const override;
|
||||||
unsigned int GetFrameCount() const;
|
unsigned int GetFrameCount() const;
|
||||||
const NzIndexBuffer* GetIndexBuffer() const override;
|
const NzIndexBuffer* GetIndexBuffer() const override;
|
||||||
bool GetVertex(NzMeshVertex* dest, unsigned int frameIndex, unsigned int vertexIndex, bool queryUV = true) const;
|
void GetVertex(unsigned int frameIndex, unsigned int vertexIndex, NzMeshVertex* dest) const;
|
||||||
const NzVertexBuffer* GetVertexBuffer() const override;
|
const NzVertexBuffer* GetVertexBuffer() const override;
|
||||||
|
|
||||||
void Interpolate(const NzAnimation* animation, unsigned int frameA, unsigned int frameB, float interpolation) const;
|
void Interpolate(const NzAnimation* animation, unsigned int frameA, unsigned int frameB, float interpolation) const;
|
||||||
|
|
@ -42,7 +42,8 @@ class NAZARA_API NzKeyframeMesh final : public NzSubMesh
|
||||||
|
|
||||||
void SetAABB(unsigned int frameIndex, const NzAxisAlignedBox& aabb);
|
void SetAABB(unsigned int frameIndex, const NzAxisAlignedBox& aabb);
|
||||||
void SetIndexBuffer(const NzIndexBuffer* indexBuffer);
|
void SetIndexBuffer(const NzIndexBuffer* indexBuffer);
|
||||||
bool SetVertex(const NzMeshVertex& source, unsigned int frameIndex, unsigned int vertexIndex, bool setUV = true);
|
void SetVertex(unsigned int frameIndex, unsigned int vertexIndex, const NzMeshVertex& source);
|
||||||
|
void SetTexCoords(unsigned int vertexIndex, const NzVector2f& uv);
|
||||||
|
|
||||||
void Unlock() const;
|
void Unlock() const;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ struct NzKeyframeMeshImpl
|
||||||
nzBufferAccess lockAccess;
|
nzBufferAccess lockAccess;
|
||||||
NzAxisAlignedBox* aabb;
|
NzAxisAlignedBox* aabb;
|
||||||
NzMeshVertex* lockBuffer;
|
NzMeshVertex* lockBuffer;
|
||||||
|
NzVector2f* uv;
|
||||||
NzVector3f* normals;
|
NzVector3f* normals;
|
||||||
NzVector3f* positions;
|
NzVector3f* positions;
|
||||||
NzVector3f* tangents;
|
NzVector3f* tangents;
|
||||||
|
|
@ -70,6 +71,7 @@ bool NzKeyframeMesh::Create(NzVertexBuffer* vertexBuffer, unsigned int frameCoun
|
||||||
m_impl->positions = new NzVector3f[frameCount*vertexCount];
|
m_impl->positions = new NzVector3f[frameCount*vertexCount];
|
||||||
m_impl->normals = new NzVector3f[frameCount*vertexCount];
|
m_impl->normals = new NzVector3f[frameCount*vertexCount];
|
||||||
m_impl->tangents = new NzVector3f[frameCount*vertexCount];
|
m_impl->tangents = new NzVector3f[frameCount*vertexCount];
|
||||||
|
m_impl->uv = new NzVector2f[vertexCount];
|
||||||
|
|
||||||
if (lock && !Lock(nzBufferAccess_DiscardAndWrite))
|
if (lock && !Lock(nzBufferAccess_DiscardAndWrite))
|
||||||
{
|
{
|
||||||
|
|
@ -98,6 +100,7 @@ void NzKeyframeMesh::Destroy()
|
||||||
delete[] m_impl->normals;
|
delete[] m_impl->normals;
|
||||||
delete[] m_impl->positions;
|
delete[] m_impl->positions;
|
||||||
delete[] m_impl->tangents;
|
delete[] m_impl->tangents;
|
||||||
|
delete[] m_impl->uv;
|
||||||
|
|
||||||
delete m_impl;
|
delete m_impl;
|
||||||
m_impl = nullptr;
|
m_impl = nullptr;
|
||||||
|
|
@ -161,19 +164,19 @@ const NzIndexBuffer* NzKeyframeMesh::GetIndexBuffer() const
|
||||||
return m_impl->indexBuffer;
|
return m_impl->indexBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NzKeyframeMesh::GetVertex(NzMeshVertex* dest, unsigned int frameIndex, unsigned int vertexIndex, bool queryUV) const
|
void NzKeyframeMesh::GetVertex(unsigned int frameIndex, unsigned int vertexIndex, NzMeshVertex* dest) const
|
||||||
{
|
{
|
||||||
#if NAZARA_UTILITY_SAFE
|
#if NAZARA_UTILITY_SAFE
|
||||||
if (!m_impl)
|
if (!m_impl)
|
||||||
{
|
{
|
||||||
NazaraError("Keyframe mesh not created");
|
NazaraError("Keyframe mesh not created");
|
||||||
return false;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (frameIndex >= m_impl->frameCount)
|
if (frameIndex >= m_impl->frameCount)
|
||||||
{
|
{
|
||||||
NazaraError("Frame index out of bounds (" + NzString::Number(frameIndex) + " >= " + NzString::Number(m_impl->frameCount) + ')');
|
NazaraError("Frame index out of bounds (" + NzString::Number(frameIndex) + " >= " + NzString::Number(m_impl->frameCount) + ')');
|
||||||
return false;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
@ -183,7 +186,7 @@ bool NzKeyframeMesh::GetVertex(NzMeshVertex* dest, unsigned int frameIndex, unsi
|
||||||
if (vertexIndex >= vertexCount)
|
if (vertexIndex >= vertexCount)
|
||||||
{
|
{
|
||||||
NazaraError("Vertex index out of bounds (" + NzString::Number(vertexIndex) + " >= " + NzString::Number(vertexCount) + ')');
|
NazaraError("Vertex index out of bounds (" + NzString::Number(vertexIndex) + " >= " + NzString::Number(vertexCount) + ')');
|
||||||
return false;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
@ -192,22 +195,7 @@ bool NzKeyframeMesh::GetVertex(NzMeshVertex* dest, unsigned int frameIndex, unsi
|
||||||
dest->normal = m_impl->normals[index];
|
dest->normal = m_impl->normals[index];
|
||||||
dest->position = m_impl->positions[index];
|
dest->position = m_impl->positions[index];
|
||||||
dest->tangent = m_impl->tangents[index];
|
dest->tangent = m_impl->tangents[index];
|
||||||
|
dest->uv = m_impl->uv[vertexIndex];
|
||||||
if (queryUV)
|
|
||||||
{
|
|
||||||
if (!Lock(nzBufferAccess_ReadOnly))
|
|
||||||
{
|
|
||||||
NazaraError("Failed to query UV");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
NzMeshVertex& vertex = m_impl->lockBuffer[vertexIndex];
|
|
||||||
dest->uv = vertex.uv;
|
|
||||||
|
|
||||||
Unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const NzVertexBuffer* NzKeyframeMesh::GetVertexBuffer() const
|
const NzVertexBuffer* NzKeyframeMesh::GetVertexBuffer() const
|
||||||
|
|
@ -354,19 +342,19 @@ void NzKeyframeMesh::SetIndexBuffer(const NzIndexBuffer* indexBuffer)
|
||||||
m_impl->indexBuffer = indexBuffer;
|
m_impl->indexBuffer = indexBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NzKeyframeMesh::SetVertex(const NzMeshVertex& source, unsigned int frameIndex, unsigned int vertexIndex, bool setUV)
|
void NzKeyframeMesh::SetVertex(unsigned int frameIndex, unsigned int vertexIndex, const NzMeshVertex& source)
|
||||||
{
|
{
|
||||||
#if NAZARA_UTILITY_SAFE
|
#if NAZARA_UTILITY_SAFE
|
||||||
if (!m_impl)
|
if (!m_impl)
|
||||||
{
|
{
|
||||||
NazaraError("Keyframe mesh not created");
|
NazaraError("Keyframe mesh not created");
|
||||||
return false;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (frameIndex >= m_impl->frameCount)
|
if (frameIndex >= m_impl->frameCount)
|
||||||
{
|
{
|
||||||
NazaraError("Frame index out of bounds (" + NzString::Number(frameIndex) + " >= " + NzString::Number(m_impl->frameCount) + ')');
|
NazaraError("Frame index out of bounds (" + NzString::Number(frameIndex) + " >= " + NzString::Number(m_impl->frameCount) + ')');
|
||||||
return false;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
@ -376,7 +364,7 @@ bool NzKeyframeMesh::SetVertex(const NzMeshVertex& source, unsigned int frameInd
|
||||||
if (vertexIndex >= vertexCount)
|
if (vertexIndex >= vertexCount)
|
||||||
{
|
{
|
||||||
NazaraError("Vertex index out of bounds (" + NzString::Number(vertexIndex) + " >= " + NzString::Number(vertexCount) + ')');
|
NazaraError("Vertex index out of bounds (" + NzString::Number(vertexIndex) + " >= " + NzString::Number(vertexCount) + ')');
|
||||||
return false;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
@ -385,22 +373,25 @@ bool NzKeyframeMesh::SetVertex(const NzMeshVertex& source, unsigned int frameInd
|
||||||
m_impl->normals[index] = source.normal;
|
m_impl->normals[index] = source.normal;
|
||||||
m_impl->positions[index] = source.position;
|
m_impl->positions[index] = source.position;
|
||||||
m_impl->tangents[index] = source.tangent;
|
m_impl->tangents[index] = source.tangent;
|
||||||
|
}
|
||||||
|
|
||||||
if (setUV)
|
void NzKeyframeMesh::SetTexCoords(unsigned int vertexIndex, const NzVector2f& uv)
|
||||||
|
{
|
||||||
|
#if NAZARA_UTILITY_SAFE
|
||||||
|
if (!m_impl)
|
||||||
{
|
{
|
||||||
if (!Lock(nzBufferAccess_WriteOnly))
|
NazaraError("Keyframe mesh not created");
|
||||||
{
|
return;
|
||||||
NazaraError("Failed to write UV");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
NzMeshVertex& vertex = m_impl->lockBuffer[vertexIndex];
|
|
||||||
vertex.uv = source.uv;
|
|
||||||
|
|
||||||
Unlock();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
if (vertexIndex >= m_impl->vertexBuffer->GetVertexCount())
|
||||||
|
{
|
||||||
|
NazaraError("Vertex index out of bounds (" + NzString::Number(vertexIndex) + " >= " + NzString::Number(m_impl->vertexBuffer->GetVertexCount()) + ')');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
m_impl->uv[vertexIndex] = uv;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NzKeyframeMesh::Unlock() const
|
void NzKeyframeMesh::Unlock() const
|
||||||
|
|
@ -439,7 +430,7 @@ void NzKeyframeMesh::InterpolateImpl(unsigned int frameA, unsigned int frameB, f
|
||||||
// Interpolation de l'AABB
|
// Interpolation de l'AABB
|
||||||
m_impl->aabb[0] = NzAxisAlignedBox::Lerp(m_impl->aabb[frameA+1], m_impl->aabb[frameB+1], interpolation);
|
m_impl->aabb[0] = NzAxisAlignedBox::Lerp(m_impl->aabb[frameA+1], m_impl->aabb[frameB+1], interpolation);
|
||||||
|
|
||||||
if (!Lock(nzBufferAccess_WriteOnly))
|
if (!Lock(nzBufferAccess_DiscardAndWrite))
|
||||||
{
|
{
|
||||||
NazaraError("Failed to lock vertex buffer");
|
NazaraError("Failed to lock vertex buffer");
|
||||||
return;
|
return;
|
||||||
|
|
@ -457,6 +448,7 @@ void NzKeyframeMesh::InterpolateImpl(unsigned int frameA, unsigned int frameB, f
|
||||||
vertex->normal = NzVector3f::Lerp(m_impl->positions[frameA+i], m_impl->positions[frameB+i], interpolation);
|
vertex->normal = NzVector3f::Lerp(m_impl->positions[frameA+i], m_impl->positions[frameB+i], interpolation);
|
||||||
vertex->position = NzVector3f::Lerp(m_impl->positions[frameA+i], m_impl->positions[frameB+i], interpolation);
|
vertex->position = NzVector3f::Lerp(m_impl->positions[frameA+i], m_impl->positions[frameB+i], interpolation);
|
||||||
vertex->tangent = NzVector3f::Lerp(m_impl->positions[frameA+i], m_impl->positions[frameB+i], interpolation);
|
vertex->tangent = NzVector3f::Lerp(m_impl->positions[frameA+i], m_impl->positions[frameB+i], interpolation);
|
||||||
|
vertex->uv = m_impl->uv[i];
|
||||||
|
|
||||||
vertex++;
|
vertex++;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -103,7 +103,7 @@ namespace
|
||||||
|
|
||||||
/// Chargement des submesh
|
/// Chargement des submesh
|
||||||
// Actuellement le loader ne charge qu'un submesh
|
// Actuellement le loader ne charge qu'un submesh
|
||||||
// TODO: Utiliser les commandes OpenGL pour créer des indices et accélérer le rendu
|
// FIXME: Utiliser les commandes OpenGL ?
|
||||||
unsigned int vertexCount = header.num_tris * 3;
|
unsigned int vertexCount = header.num_tris * 3;
|
||||||
|
|
||||||
std::unique_ptr<NzVertexBuffer> vertexBuffer(new NzVertexBuffer(NzMesh::GetDeclaration(), vertexCount, parameters.storage, nzBufferUsage_Dynamic));
|
std::unique_ptr<NzVertexBuffer> vertexBuffer(new NzVertexBuffer(NzMesh::GetDeclaration(), vertexCount, parameters.storage, nzBufferUsage_Dynamic));
|
||||||
|
|
@ -194,15 +194,15 @@ namespace
|
||||||
vertex.normal = md2Normals[vert.n];
|
vertex.normal = md2Normals[vert.n];
|
||||||
vertex.position = position;
|
vertex.position = position;
|
||||||
|
|
||||||
// On ne définit les coordonnées de texture que pour la première frame
|
unsigned int vertexIndex = vertexCount - (t*3 + v) - 1;
|
||||||
bool firstFrame = (f == 0);
|
if (f == 0)
|
||||||
if (firstFrame)
|
|
||||||
{
|
{
|
||||||
|
// On ne définit les coordonnées de texture que lors de la première frame
|
||||||
const md2_texCoord& texC = texCoords[triangles[t].texCoords[v]];
|
const md2_texCoord& texC = texCoords[triangles[t].texCoords[v]];
|
||||||
vertex.uv.Set(texC.u / static_cast<float>(header.skinwidth), 1.f - texC.v / static_cast<float>(header.skinheight));
|
subMesh->SetTexCoords(vertexIndex, NzVector2f(texC.u / static_cast<float>(header.skinwidth), 1.f - texC.v / static_cast<float>(header.skinheight)));
|
||||||
}
|
}
|
||||||
|
|
||||||
subMesh->SetVertex(vertex, f, vertexCount - (t*3 + v) - 1, firstFrame);
|
subMesh->SetVertex(f, vertexIndex, vertex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue