Reworked IndexBuffer, Vertex[Buffer|Declaration|Structs]

Former-commit-id: e3f637f2680afda57a444f73b8f7ad681bb1b8a5
This commit is contained in:
Lynix
2013-07-01 16:14:29 +02:00
parent 35d9a2fef7
commit 4abefc3e93
32 changed files with 713 additions and 1101 deletions

View File

@@ -22,17 +22,16 @@ namespace
NzBuffer::NzBuffer(nzBufferType type) :
m_type(type),
m_typeSize(0),
m_impl(nullptr),
m_length(0)
m_size(0)
{
}
NzBuffer::NzBuffer(nzBufferType type, unsigned int length, nzUInt8 typeSize, nzBufferStorage storage, nzBufferUsage usage) :
NzBuffer::NzBuffer(nzBufferType type, unsigned int size, nzBufferStorage storage, nzBufferUsage usage) :
m_type(type),
m_impl(nullptr)
{
Create(length, typeSize, storage, usage);
Create(size, storage, usage);
#ifdef NAZARA_DEBUG
if (!m_impl)
@@ -62,20 +61,14 @@ bool NzBuffer::CopyContent(const NzBuffer& buffer)
NazaraError("Source buffer must be valid");
return false;
}
if (!buffer.GetTypeSize() != m_typeSize)
{
NazaraError("Source buffer type size does not match buffer type size");
return false;
}
#endif
NzBufferMapper<NzBuffer> mapper(buffer, nzBufferAccess_ReadOnly);
return Fill(mapper.GetPointer(), 0, buffer.GetLength());
return Fill(mapper.GetPointer(), 0, buffer.GetSize());
}
bool NzBuffer::Create(unsigned int length, nzUInt8 typeSize, nzBufferStorage storage, nzBufferUsage usage)
bool NzBuffer::Create(unsigned int size, nzBufferStorage storage, nzBufferUsage usage)
{
Destroy();
@@ -87,7 +80,7 @@ bool NzBuffer::Create(unsigned int length, nzUInt8 typeSize, nzBufferStorage sto
}
NzAbstractBuffer* impl = s_bufferFunctions[storage](this, m_type);
if (!impl->Create(length*typeSize, usage))
if (!impl->Create(size, usage))
{
NazaraError("Failed to create buffer");
delete impl;
@@ -96,8 +89,7 @@ bool NzBuffer::Create(unsigned int length, nzUInt8 typeSize, nzBufferStorage sto
}
m_impl = impl;
m_length = length;
m_typeSize = typeSize;
m_size = size;
m_storage = storage;
m_usage = usage;
@@ -117,7 +109,7 @@ void NzBuffer::Destroy()
}
}
bool NzBuffer::Fill(const void* data, unsigned int offset, unsigned int length, bool forceDiscard)
bool NzBuffer::Fill(const void* data, unsigned int offset, unsigned int size, bool forceDiscard)
{
#if NAZARA_UTILITY_SAFE
if (!m_impl)
@@ -126,14 +118,14 @@ bool NzBuffer::Fill(const void* data, unsigned int offset, unsigned int length,
return false;
}
if (offset+length > m_length)
if (offset+size > m_size)
{
NazaraError("Exceeding buffer size");
return false;
}
#endif
return m_impl->Fill(data, offset*m_typeSize, ((length == 0) ? m_length-offset : length)*m_typeSize, forceDiscard);
return m_impl->Fill(data, offset, (size == 0) ? m_size-offset : size, forceDiscard);
}
NzAbstractBuffer* NzBuffer::GetImpl() const
@@ -141,40 +133,9 @@ NzAbstractBuffer* NzBuffer::GetImpl() const
return m_impl;
}
unsigned int NzBuffer::GetLength() const
{
return m_length;
}
void* NzBuffer::GetPointer()
{
#if NAZARA_UTILITY_SAFE
if (!m_impl)
{
NazaraError("Buffer not valid");
return nullptr;
}
#endif
return m_impl->GetPointer();
}
const void* NzBuffer::GetPointer() const
{
#if NAZARA_UTILITY_SAFE
if (!m_impl)
{
NazaraError("Buffer not valid");
return nullptr;
}
#endif
return m_impl->GetPointer();
}
unsigned int NzBuffer::GetSize() const
{
return m_length*m_typeSize;
return m_size;
}
nzBufferStorage NzBuffer::GetStorage() const
@@ -187,11 +148,6 @@ nzBufferType NzBuffer::GetType() const
return m_type;
}
nzUInt8 NzBuffer::GetTypeSize() const
{
return m_typeSize;
}
nzBufferUsage NzBuffer::GetUsage() const
{
return m_usage;
@@ -207,7 +163,7 @@ bool NzBuffer::IsValid() const
return m_impl != nullptr;
}
void* NzBuffer::Map(nzBufferAccess access, unsigned int offset, unsigned int length)
void* NzBuffer::Map(nzBufferAccess access, unsigned int offset, unsigned int size)
{
#if NAZARA_UTILITY_SAFE
if (!m_impl)
@@ -216,17 +172,17 @@ void* NzBuffer::Map(nzBufferAccess access, unsigned int offset, unsigned int len
return nullptr;
}
if (offset+length > m_length)
if (offset+size > m_size)
{
NazaraError("Exceeding buffer size");
return nullptr;
}
#endif
return m_impl->Map(access, offset*m_typeSize, ((length == 0) ? m_length-offset : length)*m_typeSize);
return m_impl->Map(access, offset, (size == 0) ? m_size-offset : size);
}
void* NzBuffer::Map(nzBufferAccess access, unsigned int offset, unsigned int length) const
void* NzBuffer::Map(nzBufferAccess access, unsigned int offset, unsigned int size) const
{
#if NAZARA_UTILITY_SAFE
if (!m_impl)
@@ -241,14 +197,14 @@ void* NzBuffer::Map(nzBufferAccess access, unsigned int offset, unsigned int len
return nullptr;
}
if (offset+length > m_length)
if (offset+size > m_size)
{
NazaraError("Exceeding buffer size");
return nullptr;
}
#endif
return m_impl->Map(access, offset*m_typeSize, ((length == 0) ? m_length-offset : length)*m_typeSize);
return m_impl->Map(access, offset, (size == 0) ? m_size-offset : size);
}
bool NzBuffer::SetStorage(nzBufferStorage storage)
@@ -272,7 +228,7 @@ bool NzBuffer::SetStorage(nzBufferStorage storage)
}
#endif
void* ptr = m_impl->Map(nzBufferAccess_ReadOnly, 0, m_length*m_typeSize);
void* ptr = m_impl->Map(nzBufferAccess_ReadOnly, 0, m_size);
if (!ptr)
{
NazaraError("Failed to map buffer");
@@ -280,7 +236,7 @@ bool NzBuffer::SetStorage(nzBufferStorage storage)
}
NzAbstractBuffer* impl = s_bufferFunctions[storage](this, m_type);
if (!impl->Create(m_length*m_typeSize, m_usage))
if (!impl->Create(m_size, m_usage))
{
NazaraError("Failed to create buffer");
delete impl;
@@ -289,7 +245,7 @@ bool NzBuffer::SetStorage(nzBufferStorage storage)
return false;
}
if (!impl->Fill(ptr, 0, m_length*m_typeSize))
if (!impl->Fill(ptr, 0, m_size))
{
NazaraError("Failed to fill buffer");
impl->Destroy();

View File

@@ -50,7 +50,7 @@ m_sharedImage(&emptyImage)
}
NzImage::NzImage(const NzImage& image) :
NzResource(image),
NzResource(),
m_sharedImage(image.m_sharedImage)
{
if (m_sharedImage != &emptyImage)
@@ -63,6 +63,11 @@ m_sharedImage(image.m_sharedImage)
image.m_sharedImage = &emptyImage;
}
NzImage::NzImage(SharedImage* sharedImage) :
m_sharedImage(sharedImage)
{
}
NzImage::~NzImage()
{
Destroy();

View File

@@ -11,62 +11,65 @@
#include <stdexcept>
#include <Nazara/Utility/Debug.hpp>
///FIXME: Gérer efficacement les erreurs de création du buffer
NzIndexBuffer::NzIndexBuffer(NzBuffer* buffer, unsigned int startIndex, unsigned int indexCount) :
NzIndexBuffer::NzIndexBuffer(bool largeIndices, NzBuffer* buffer, unsigned int startOffset, unsigned int endOffset) :
m_buffer(buffer),
m_ownsBuffer(false),
m_indexCount(indexCount),
m_startIndex(startIndex)
m_largeIndices(largeIndices),
m_endOffset(endOffset),
m_startOffset(startOffset)
{
if (m_buffer)
#ifdef NAZARA_DEBUG
if (!m_buffer || !m_buffer->IsValid())
{
#ifdef NAZARA_DEBUG
nzUInt8 indexSize = m_buffer->GetSize();
if (indexSize != 2 && indexSize != 4)
{
NazaraError("Invalid index size (" + NzString::Number(indexSize) + ')');
m_buffer = nullptr;
throw std::runtime_error("Constructor failed");
}
#endif
NazaraError("Buffer is invalid");
throw std::invalid_argument("Buffer must be valid");
}
if (endOffset > startOffset)
{
NazaraError("End offset cannot be over start offset");
throw std::invalid_argument("End offset cannot be over start offset");
}
unsigned int bufferSize = m_buffer->GetSize();
if (startOffset >= bufferSize)
{
NazaraError("Start offset is over buffer size");
throw std::invalid_argument("Start offset is over buffer size");
}
if (endOffset >= bufferSize)
{
NazaraError("End offset is over buffer size");
throw std::invalid_argument("End offset is over buffer size");
}
#endif
unsigned int stride = (largeIndices) ? sizeof(nzUInt32) : sizeof(nzUInt16);
m_indexCount = (endOffset - startOffset) / stride;
}
NzIndexBuffer::NzIndexBuffer(unsigned int length, bool largeIndices, nzBufferStorage storage, nzBufferUsage usage) :
m_ownsBuffer(true),
NzIndexBuffer::NzIndexBuffer(bool largeIndices, unsigned int length, nzBufferStorage storage, nzBufferUsage usage) :
m_largeIndices(largeIndices),
m_indexCount(length),
m_startIndex(0)
m_startOffset(0)
{
m_buffer = new NzBuffer(nzBufferType_Index, length, (largeIndices) ? 4 : 2, storage, usage);
m_endOffset = length * ((largeIndices) ? sizeof(nzUInt32) : sizeof(nzUInt16));
m_buffer = new NzBuffer(nzBufferType_Index, m_endOffset, storage, usage);
m_buffer->SetPersistent(false);
}
NzIndexBuffer::NzIndexBuffer(const NzIndexBuffer& indexBuffer) :
NzResource(true),
NzResource(),
m_buffer(indexBuffer.m_buffer),
m_ownsBuffer(indexBuffer.m_ownsBuffer),
m_largeIndices(indexBuffer.m_largeIndices),
m_endOffset(indexBuffer.m_endOffset),
m_indexCount(indexBuffer.m_indexCount),
m_startIndex(indexBuffer.m_startIndex)
m_startOffset(indexBuffer.m_startOffset)
{
if (m_buffer)
{
if (m_ownsBuffer)
{
NzBuffer* buffer = indexBuffer.m_buffer;
m_buffer = new NzBuffer(nzBufferType_Index, buffer->GetLength(), buffer->GetSize(), buffer->GetStorage(), buffer->GetUsage());
m_buffer->SetPersistent(false);
m_buffer->CopyContent(*indexBuffer.m_buffer);
}
else
m_buffer = indexBuffer.m_buffer;
}
}
NzIndexBuffer::~NzIndexBuffer() = default;
unsigned int NzIndexBuffer::ComputeCacheMissCount() const
{
NzIndexMapper mapper(this);
@@ -74,23 +77,23 @@ unsigned int NzIndexBuffer::ComputeCacheMissCount() const
return NzComputeCacheMissCount(mapper.begin(), m_indexCount);
}
bool NzIndexBuffer::Fill(const void* data, unsigned int offset, unsigned int length, bool forceDiscard)
bool NzIndexBuffer::Fill(const void* data, unsigned int offset, unsigned int size, bool forceDiscard)
{
#if NAZARA_UTILITY_SAFE
if (!m_buffer)
{
NazaraError("Impossible to fill sequential buffers");
return false;
}
if (offset+length > m_indexCount)
if (m_startOffset + offset + size > m_endOffset)
{
NazaraError("Exceeding virtual buffer size");
return false;
}
#endif
return m_buffer->Fill(data, m_startIndex+offset, length, forceDiscard);
return m_buffer->Fill(data, m_startOffset+offset, size, forceDiscard);
}
bool NzIndexBuffer::FillIndices(const void* data, unsigned int startIndex, unsigned int length, bool forceDiscard)
{
unsigned int stride = GetStride();
return Fill(data, startIndex*stride, length*stride, forceDiscard);
}
NzBuffer* NzIndexBuffer::GetBuffer() const
@@ -98,30 +101,9 @@ NzBuffer* NzIndexBuffer::GetBuffer() const
return m_buffer;
}
void* NzIndexBuffer::GetPointer()
unsigned int NzIndexBuffer::GetEndOffset() const
{
#if NAZARA_UTILITY_SAFE
if (!m_buffer)
{
NazaraError("Sequential buffers have no pointer");
return nullptr;
}
#endif
return reinterpret_cast<nzUInt8*>(m_buffer->GetPointer()) + m_startIndex*m_buffer->GetTypeSize();
}
const void* NzIndexBuffer::GetPointer() const
{
#if NAZARA_UTILITY_SAFE
if (!m_buffer)
{
NazaraError("Sequential buffers have no pointer");
return nullptr;
}
#endif
return reinterpret_cast<const nzUInt8*>(m_buffer->GetPointer()) + m_startIndex*m_buffer->GetTypeSize();
return m_endOffset;
}
unsigned int NzIndexBuffer::GetIndexCount() const
@@ -129,78 +111,64 @@ unsigned int NzIndexBuffer::GetIndexCount() const
return m_indexCount;
}
unsigned int NzIndexBuffer::GetStartIndex() const
unsigned int NzIndexBuffer::GetStride() const
{
return m_startIndex;
return (m_largeIndices) ? sizeof(nzUInt32) : sizeof(nzUInt16);
}
unsigned int NzIndexBuffer::GetStartOffset() const
{
return m_startOffset;
}
bool NzIndexBuffer::HasLargeIndices() const
{
#if NAZARA_UTILITY_SAFE
if (!m_buffer)
{
NazaraError("Sequential buffers have no index size");
return 0;
}
#endif
return (m_buffer->GetTypeSize() == 4);
return m_largeIndices;
}
bool NzIndexBuffer::IsHardware() const
{
return m_buffer->IsHardware();
}
void* NzIndexBuffer::Map(nzBufferAccess access, unsigned int offset, unsigned int size)
{
#if NAZARA_UTILITY_SAFE
if (!m_buffer)
if (m_startOffset + offset + size > m_endOffset)
{
NazaraWarning("Sequential index buffers are neither hardware or software");
NazaraError("Exceeding virtual buffer size");
return false;
}
#endif
return m_buffer->IsHardware();
return m_buffer->Map(access, offset, size);
}
bool NzIndexBuffer::IsSequential() const
{
return m_buffer == nullptr;
}
void* NzIndexBuffer::Map(nzBufferAccess access, unsigned int offset, unsigned int length)
void* NzIndexBuffer::Map(nzBufferAccess access, unsigned int offset, unsigned int size) const
{
#if NAZARA_UTILITY_SAFE
if (!m_buffer)
{
NazaraError("Impossible to map sequential buffers");
return nullptr;
}
if (offset+length > m_indexCount)
if (m_startOffset + offset + size > m_endOffset)
{
NazaraError("Exceeding virtual buffer size");
return nullptr;
}
#endif
return m_buffer->Map(access, m_startIndex+offset, (length) ? length : m_indexCount-offset);
return m_buffer->Map(access, offset, size);
}
void* NzIndexBuffer::Map(nzBufferAccess access, unsigned int offset, unsigned int length) const
void* NzIndexBuffer::MapIndices(nzBufferAccess access, unsigned int startIndex, unsigned int length)
{
#if NAZARA_UTILITY_SAFE
if (!m_buffer)
{
NazaraError("Impossible to map sequential buffers");
return nullptr;
}
unsigned int stride = GetStride();
if (offset+length > m_indexCount)
{
NazaraError("Exceeding virtual buffer size");
return nullptr;
}
#endif
return Map(access, startIndex*stride, length*stride);
}
return m_buffer->Map(access, m_startIndex+offset, (length) ? length : m_indexCount-offset);
void* NzIndexBuffer::MapIndices(nzBufferAccess access, unsigned int startIndex, unsigned int length) const
{
unsigned int stride = GetStride();
return Map(access, startIndex*stride, length*stride);
}
void NzIndexBuffer::Optimize()
@@ -212,26 +180,10 @@ void NzIndexBuffer::Optimize()
bool NzIndexBuffer::SetStorage(nzBufferStorage storage)
{
#if NAZARA_UTILITY_SAFE
if (!m_buffer)
{
NazaraWarning("Sequential buffers have no storage");
return true;
}
#endif
return m_buffer->SetStorage(storage);
}
void NzIndexBuffer::Unmap() const
{
#if NAZARA_UTILITY_SAFE
if (!m_buffer)
{
NazaraError("Impossible to unlock sequential buffers");
return;
}
#endif
m_buffer->Unmap();
}

View File

@@ -22,13 +22,6 @@ namespace
return ptr[i];
}
nzUInt32 GetterSequential(const void* buffer, unsigned int i)
{
NazaraUnused(buffer);
return static_cast<nzUInt32>(i);
}
void Setter16(void* buffer, unsigned int i, nzUInt32 value)
{
nzUInt16* ptr = reinterpret_cast<nzUInt16*>(buffer);
@@ -50,32 +43,32 @@ namespace
NzIndexMapper::NzIndexMapper(NzIndexBuffer* indexBuffer, nzBufferAccess access) :
m_indexCount(indexBuffer->GetIndexCount())
{
if (indexBuffer && !indexBuffer->IsSequential())
#if NAZARA_UTILITY_SAFE
if (!indexBuffer)
{
if (!m_mapper.Map(indexBuffer, access))
NazaraError("Failed to map buffer"); ///TODO: Unexcepted
NazaraError("Index buffer must be valid");
return;
}
#endif
if (indexBuffer->HasLargeIndices())
{
m_getter = Getter32;
if (access != nzBufferAccess_ReadOnly)
m_setter = Setter32;
else
m_setter = SetterError;
}
if (!m_mapper.Map(indexBuffer, access))
NazaraError("Failed to map buffer"); ///TODO: Unexcepted
if (indexBuffer->HasLargeIndices())
{
m_getter = Getter32;
if (access != nzBufferAccess_ReadOnly)
m_setter = Setter32;
else
{
m_getter = Getter16;
if (access != nzBufferAccess_ReadOnly)
m_setter = Setter16;
else
m_setter = SetterError;
}
m_setter = SetterError;
}
else
{
m_getter = GetterSequential;
m_setter = SetterError;
m_getter = Getter16;
if (access != nzBufferAccess_ReadOnly)
m_setter = Setter16;
else
m_setter = SetterError;
}
}
@@ -83,18 +76,21 @@ NzIndexMapper::NzIndexMapper(const NzIndexBuffer* indexBuffer, nzBufferAccess ac
m_setter(SetterError),
m_indexCount(indexBuffer->GetIndexCount())
{
if (indexBuffer && !indexBuffer->IsSequential())
#if NAZARA_UTILITY_SAFE
if (!indexBuffer)
{
if (!m_mapper.Map(indexBuffer, access))
NazaraError("Failed to map buffer"); ///TODO: Unexcepted
if (indexBuffer->HasLargeIndices())
m_getter = Getter32;
else
m_getter = Getter16;
NazaraError("Index buffer must be valid");
return;
}
#endif
if (!m_mapper.Map(indexBuffer, access))
NazaraError("Failed to map buffer"); ///TODO: Unexcepted
if (indexBuffer->HasLargeIndices())
m_getter = Getter32;
else
m_getter = GetterSequential;
m_getter = Getter16;
}
NzIndexMapper::NzIndexMapper(const NzSubMesh* subMesh) :

View File

@@ -102,7 +102,7 @@ namespace
/// Chargement des submesh
// Actuellement le loader ne charge qu'un submesh
std::unique_ptr<NzIndexBuffer> indexBuffer(new NzIndexBuffer(header.num_tris * 3, false, parameters.storage, nzBufferUsage_Static));
std::unique_ptr<NzIndexBuffer> indexBuffer(new NzIndexBuffer(false, header.num_tris * 3, parameters.storage, nzBufferUsage_Static));
indexBuffer->SetPersistent(false);
/// Lecture des triangles
@@ -149,7 +149,7 @@ namespace
}
#endif
std::unique_ptr<NzVertexBuffer> vertexBuffer(new NzVertexBuffer(NzMesh::GetDeclaration(), header.num_vertices, parameters.storage, nzBufferUsage_Static));
std::unique_ptr<NzVertexBuffer> vertexBuffer(new NzVertexBuffer(NzVertexDeclaration::Get(nzVertexLayout_XYZ_Normal_UV_Tangent), header.num_vertices, parameters.storage, nzBufferUsage_Static));
std::unique_ptr<NzStaticMesh> subMesh(new NzStaticMesh(mesh));
if (!subMesh->Create(vertexBuffer.get()))
{

View File

@@ -292,7 +292,7 @@ bool NzMD5MeshParser::Parse(NzMesh* mesh)
// Index buffer
bool largeIndices = (vertexCount > std::numeric_limits<nzUInt16>::max());
std::unique_ptr<NzIndexBuffer> indexBuffer(new NzIndexBuffer(indexCount, largeIndices, m_parameters.storage));
std::unique_ptr<NzIndexBuffer> indexBuffer(new NzIndexBuffer(largeIndices, indexCount, m_parameters.storage));
indexBuffer->SetPersistent(false);
NzIndexMapper indexMapper(indexBuffer.get(), nzBufferAccess_DiscardAndWrite);
@@ -308,7 +308,7 @@ bool NzMD5MeshParser::Parse(NzMesh* mesh)
indexMapper.Unmap();
// Vertex buffer
std::unique_ptr<NzVertexBuffer> vertexBuffer(new NzVertexBuffer(NzMesh::GetDeclaration(), vertexCount, m_parameters.storage));
std::unique_ptr<NzVertexBuffer> vertexBuffer(new NzVertexBuffer(NzVertexDeclaration::Get(nzVertexLayout_XYZ_Normal_UV_Tangent), vertexCount, m_parameters.storage));
NzBufferMapper<NzVertexBuffer> vertexMapper(vertexBuffer.get(), nzBufferAccess_WriteOnly);
NzMeshVertex* vertex = reinterpret_cast<NzMeshVertex*>(vertexMapper.GetPointer());

View File

@@ -170,6 +170,8 @@ NzSubMesh* NzMesh::BuildSubMesh(const NzPrimitive& primitive, const NzMeshParams
NzMatrix4f matrix(primitive.matrix);
matrix.ApplyScale(params.scale);
NzVertexDeclaration* declaration = NzVertexDeclaration::Get(nzVertexLayout_XYZ_Normal_UV_Tangent);
switch (primitive.type)
{
case nzPrimitiveType_Box:
@@ -181,7 +183,7 @@ NzSubMesh* NzMesh::BuildSubMesh(const NzPrimitive& primitive, const NzMeshParams
indexBuffer.reset(new NzIndexBuffer(indexCount, vertexCount > std::numeric_limits<nzUInt16>::max(), params.storage, nzBufferUsage_Static));
indexBuffer->SetPersistent(false);
vertexBuffer.reset(new NzVertexBuffer(GetDeclaration(), vertexCount, params.storage, nzBufferUsage_Static));
vertexBuffer.reset(new NzVertexBuffer(declaration, vertexCount, params.storage, nzBufferUsage_Static));
vertexBuffer->SetPersistent(false);
NzBufferMapper<NzVertexBuffer> vertexMapper(vertexBuffer.get(), nzBufferAccess_WriteOnly);
@@ -200,7 +202,7 @@ NzSubMesh* NzMesh::BuildSubMesh(const NzPrimitive& primitive, const NzMeshParams
indexBuffer.reset(new NzIndexBuffer(indexCount, vertexCount > std::numeric_limits<nzUInt16>::max(), params.storage, nzBufferUsage_Static));
indexBuffer->SetPersistent(false);
vertexBuffer.reset(new NzVertexBuffer(GetDeclaration(), vertexCount, params.storage, nzBufferUsage_Static));
vertexBuffer.reset(new NzVertexBuffer(declaration, vertexCount, params.storage, nzBufferUsage_Static));
vertexBuffer->SetPersistent(false);
NzBufferMapper<NzVertexBuffer> vertexMapper(vertexBuffer.get(), nzBufferAccess_WriteOnly);
@@ -223,7 +225,7 @@ NzSubMesh* NzMesh::BuildSubMesh(const NzPrimitive& primitive, const NzMeshParams
indexBuffer.reset(new NzIndexBuffer(indexCount, vertexCount > std::numeric_limits<nzUInt16>::max(), params.storage, nzBufferUsage_Static));
indexBuffer->SetPersistent(false);
vertexBuffer.reset(new NzVertexBuffer(GetDeclaration(), vertexCount, params.storage, nzBufferUsage_Static));
vertexBuffer.reset(new NzVertexBuffer(declaration, vertexCount, params.storage, nzBufferUsage_Static));
vertexBuffer->SetPersistent(false);
NzBufferMapper<NzVertexBuffer> vertexMapper(vertexBuffer.get(), nzBufferAccess_WriteOnly);
@@ -242,7 +244,7 @@ NzSubMesh* NzMesh::BuildSubMesh(const NzPrimitive& primitive, const NzMeshParams
indexBuffer.reset(new NzIndexBuffer(indexCount, vertexCount > std::numeric_limits<nzUInt16>::max(), params.storage, nzBufferUsage_Static));
indexBuffer->SetPersistent(false);
vertexBuffer.reset(new NzVertexBuffer(GetDeclaration(), vertexCount, params.storage, nzBufferUsage_Static));
vertexBuffer.reset(new NzVertexBuffer(declaration, vertexCount, params.storage, nzBufferUsage_Static));
vertexBuffer->SetPersistent(false);
NzBufferMapper<NzVertexBuffer> vertexMapper(vertexBuffer.get(), nzBufferAccess_WriteOnly);
@@ -261,7 +263,7 @@ NzSubMesh* NzMesh::BuildSubMesh(const NzPrimitive& primitive, const NzMeshParams
indexBuffer.reset(new NzIndexBuffer(indexCount, vertexCount > std::numeric_limits<nzUInt16>::max(), params.storage, nzBufferUsage_Static));
indexBuffer->SetPersistent(false);
vertexBuffer.reset(new NzVertexBuffer(GetDeclaration(), vertexCount, params.storage, nzBufferUsage_Static));
vertexBuffer.reset(new NzVertexBuffer(declaration, vertexCount, params.storage, nzBufferUsage_Static));
vertexBuffer->SetPersistent(false);
NzBufferMapper<NzVertexBuffer> vertexMapper(vertexBuffer.get(), nzBufferAccess_WriteOnly);
@@ -979,36 +981,6 @@ void NzMesh::Transform(const NzMatrix4f& matrix)
m_impl->aabbUpdated = false;
}
const NzVertexDeclaration* NzMesh::GetDeclaration()
{
static NzVertexDeclaration declaration;
if (!declaration.IsValid())
{
// Déclaration correspondant à NzVertexStruct_XYZ_Normal_UV_Tangent
NzVertexElement elements[4];
elements[0].offset = 0;
elements[0].type = nzElementType_Float3;
elements[0].usage = nzElementUsage_Position;
elements[1].offset = 3*sizeof(float);
elements[1].type = nzElementType_Float3;
elements[1].usage = nzElementUsage_Normal;
elements[2].offset = 3*sizeof(float) + 3*sizeof(float);
elements[2].type = nzElementType_Float2;
elements[2].usage = nzElementUsage_TexCoord;
elements[3].offset = 3*sizeof(float) + 3*sizeof(float) + 2*sizeof(float);
elements[3].type = nzElementType_Float3;
elements[3].usage = nzElementUsage_Tangent;
declaration.Create(elements, 4);
}
return &declaration;
}
void NzMesh::OnResourceReleased(const NzResource* resource, int index)
{
NazaraUnused(resource);

View File

@@ -61,11 +61,6 @@ bool NzSoftwareBuffer::Fill(const void* data, unsigned int offset, unsigned int
return true;
}
void* NzSoftwareBuffer::GetPointer()
{
return m_buffer;
}
bool NzSoftwareBuffer::IsHardware() const
{
return false;

View File

@@ -21,8 +21,6 @@ class NzSoftwareBuffer : public NzAbstractBuffer
bool Fill(const void* data, unsigned int offset, unsigned int size, bool forceDiscard);
void* GetPointer();
bool IsHardware() const;
void* Map(nzBufferAccess access, unsigned int offset = 0, unsigned int size = 0);

View File

@@ -16,6 +16,7 @@
#include <Nazara/Utility/Loaders/PCX.hpp>
#include <Nazara/Utility/Loaders/STB.hpp>
#include <Nazara/Utility/PixelFormat.hpp>
#include <Nazara/Utility/VertexDeclaration.hpp>
#include <Nazara/Utility/Window.hpp>
#include <Nazara/Utility/Debug.hpp>
@@ -60,6 +61,14 @@ bool NzUtility::Initialize()
return false;
}
if (!NzVertexDeclaration::Initialize())
{
NazaraError("Failed to initialize vertex declarations");
Uninitialize();
return false;
}
if (!NzWindow::Initialize())
{
NazaraError("Failed to initialize window's system");
@@ -117,6 +126,7 @@ void NzUtility::Uninitialize()
NzLoaders_STB_Unregister();
NzWindow::Uninitialize();
NzVertexDeclaration::Uninitialize();
NzPixelFormat::Uninitialize();
NzBuffer::Uninitialize();

View File

@@ -7,80 +7,95 @@
#include <stdexcept>
#include <Nazara/Utility/Debug.hpp>
///FIXME: Gérer efficacement les erreurs de création du buffer
NzVertexBuffer::NzVertexBuffer(const NzVertexDeclaration* vertexDeclaration, NzBuffer* buffer, unsigned int startVertex, unsigned int vertexCount) :
NzVertexBuffer::NzVertexBuffer(const NzVertexDeclaration* vertexDeclaration, NzBuffer* buffer, unsigned int startOffset, unsigned int endOffset) :
m_buffer(buffer),
m_vertexDeclaration(vertexDeclaration),
m_ownsBuffer(false),
m_startVertex(startVertex),
m_vertexCount(vertexCount)
m_endOffset(endOffset),
m_startOffset(startOffset)
{
#ifdef NAZARA_DEBUG
if (!m_vertexDeclaration)
{
NazaraError("Vertex declaration is invalid");
throw std::invalid_argument("Invalid vertex declaration");
}
if (!m_buffer || !m_buffer->IsValid())
{
NazaraError("Buffer is invalid");
throw std::invalid_argument("Buffer must be valid");
}
if (!m_vertexDeclaration || !m_vertexDeclaration->IsValid())
if (endOffset > startOffset)
{
NazaraError("Vertex declaration is invalid");
throw std::invalid_argument("Invalid vertex declaration");
NazaraError("End offset cannot be over start offset");
throw std::invalid_argument("End offset cannot be over start offset");
}
unsigned int bufferSize = m_buffer->GetSize();
if (startOffset >= bufferSize)
{
NazaraError("Start offset is over buffer size");
throw std::invalid_argument("Start offset is over buffer size");
}
if (endOffset >= bufferSize)
{
NazaraError("End offset is over buffer size");
throw std::invalid_argument("End offset is over buffer size");
}
#endif
m_vertexCount = (endOffset - startOffset) / m_vertexDeclaration->GetStride();
}
NzVertexBuffer::NzVertexBuffer(const NzVertexDeclaration* vertexDeclaration, unsigned int length, nzBufferStorage storage, nzBufferUsage usage) :
m_vertexDeclaration(vertexDeclaration),
m_ownsBuffer(true),
m_startVertex(0),
m_startOffset(0),
m_vertexCount(length)
{
#ifdef NAZARA_DEBUG
if (!m_vertexDeclaration || !m_vertexDeclaration->IsValid())
if (!m_vertexDeclaration)
{
NazaraError("Vertex declaration is invalid");
throw std::invalid_argument("Invalid vertex declaration");
}
#endif
m_buffer = new NzBuffer(nzBufferType_Vertex, length, vertexDeclaration->GetStride(nzElementStream_VertexData), storage, usage);
m_endOffset = length*vertexDeclaration->GetStride();
m_buffer = new NzBuffer(nzBufferType_Vertex, m_endOffset, storage, usage);
m_buffer->SetPersistent(false);
}
NzVertexBuffer::NzVertexBuffer(const NzVertexBuffer& vertexBuffer) :
NzResource(true),
NzResource(),
m_buffer(vertexBuffer.m_buffer),
m_vertexDeclaration(vertexBuffer.m_vertexDeclaration),
m_ownsBuffer(vertexBuffer.m_ownsBuffer),
m_startVertex(vertexBuffer.m_startVertex),
m_endOffset(vertexBuffer.m_endOffset),
m_startOffset(vertexBuffer.m_startOffset),
m_vertexCount(vertexBuffer.m_vertexCount)
{
if (m_ownsBuffer)
{
NzBuffer* buffer = vertexBuffer.m_buffer;
m_buffer = new NzBuffer(nzBufferType_Vertex, buffer->GetLength(), buffer->GetSize(), buffer->GetStorage(), buffer->GetUsage());
m_buffer->SetPersistent(false);
m_buffer->CopyContent(*vertexBuffer.m_buffer);
}
else
m_buffer = vertexBuffer.m_buffer;
}
NzVertexBuffer::~NzVertexBuffer() = default;
bool NzVertexBuffer::Fill(const void* data, unsigned int offset, unsigned int length, bool forceDiscard)
bool NzVertexBuffer::Fill(const void* data, unsigned int offset, unsigned int size, bool forceDiscard)
{
#if NAZARA_UTILITY_SAFE
if (offset+length > m_vertexCount)
if (m_startOffset + offset + size > m_endOffset)
{
NazaraError("Exceeding virtual buffer size");
return false;
}
#endif
return m_buffer->Fill(data, m_startVertex+offset, length, forceDiscard);
return m_buffer->Fill(data, m_startOffset+offset, size, forceDiscard);
}
bool NzVertexBuffer::FillVertices(const void* data, unsigned int startVertex, unsigned int length, bool forceDiscard)
{
unsigned int stride = m_vertexDeclaration->GetStride();
return Fill(data, startVertex*stride, length*stride, forceDiscard);
}
NzBuffer* NzVertexBuffer::GetBuffer() const
@@ -88,24 +103,19 @@ NzBuffer* NzVertexBuffer::GetBuffer() const
return m_buffer;
}
void* NzVertexBuffer::GetPointer()
unsigned int NzVertexBuffer::GetEndOffset() const
{
return reinterpret_cast<nzUInt8*>(m_buffer->GetPointer()) + m_startVertex*m_buffer->GetTypeSize();
return m_endOffset;
}
const void* NzVertexBuffer::GetPointer() const
unsigned int NzVertexBuffer::GetStartOffset() const
{
return reinterpret_cast<const nzUInt8*>(m_buffer->GetPointer()) + m_startVertex*m_buffer->GetTypeSize();
return m_startOffset;
}
unsigned int NzVertexBuffer::GetStartVertex() const
unsigned int NzVertexBuffer::GetStride() const
{
return m_startVertex;
}
nzUInt8 NzVertexBuffer::GetTypeSize() const
{
return m_buffer->GetTypeSize();
return m_vertexDeclaration->GetStride();
}
unsigned int NzVertexBuffer::GetVertexCount() const
@@ -123,30 +133,44 @@ bool NzVertexBuffer::IsHardware() const
return m_buffer->IsHardware();
}
void* NzVertexBuffer::Map(nzBufferAccess access, unsigned int offset, unsigned int length)
void* NzVertexBuffer::Map(nzBufferAccess access, unsigned int offset, unsigned int size)
{
#if NAZARA_UTILITY_SAFE
if (offset+length > m_vertexCount)
if (m_startOffset + offset + size > m_endOffset)
{
NazaraError("Exceeding virtual buffer size");
return nullptr;
return false;
}
#endif
return m_buffer->Map(access, m_startVertex+offset, (length) ? length : m_vertexCount-offset);
return m_buffer->Map(access, offset, size);
}
void* NzVertexBuffer::Map(nzBufferAccess access, unsigned int offset, unsigned int length) const
void* NzVertexBuffer::Map(nzBufferAccess access, unsigned int offset, unsigned int size) const
{
#if NAZARA_UTILITY_SAFE
if (offset+length > m_vertexCount)
if (m_startOffset + offset + size > m_endOffset)
{
NazaraError("Exceeding virtual buffer size");
return nullptr;
}
#endif
return m_buffer->Map(access, m_startVertex+offset, (length) ? length : m_vertexCount-offset);
return m_buffer->Map(access, offset, size);
}
void* NzVertexBuffer::MapVertices(nzBufferAccess access, unsigned int startVertex, unsigned int length)
{
unsigned int stride = m_vertexDeclaration->GetStride();
return Map(access, startVertex*stride, length*stride);
}
void* NzVertexBuffer::MapVertices(nzBufferAccess access, unsigned int startVertex, unsigned int length) const
{
unsigned int stride = m_vertexDeclaration->GetStride();
return Map(access, startVertex*stride, length*stride);
}
bool NzVertexBuffer::SetStorage(nzBufferStorage storage)
@@ -154,6 +178,20 @@ bool NzVertexBuffer::SetStorage(nzBufferStorage storage)
return m_buffer->SetStorage(storage);
}
void NzVertexBuffer::SetVertexDeclaration(const NzVertexDeclaration* vertexDeclaration)
{
#if NAZARA_UTILITY_SAFE
if (!vertexDeclaration)
{
NazaraError("Vertex declaration is invalid");
return;
}
#endif
m_vertexCount = (m_endOffset - m_startOffset)/vertexDeclaration->GetStride();
m_vertexDeclaration = vertexDeclaration;
}
void NzVertexBuffer::Unmap() const
{
m_buffer->Unmap();

View File

@@ -5,386 +5,192 @@
#include <Nazara/Utility/VertexDeclaration.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Utility/Config.hpp>
#include <algorithm>
#include <atomic>
#include <cstring>
#include <stdexcept>
#include <vector>
#include <Nazara/Utility/Debug.hpp>
namespace
{
const unsigned int elementCount[] =
unsigned int attributeSize[nzAttributeType_Max+1] =
{
4, // nzElementType_Color
1, // nzElementType_Double1
2, // nzElementType_Double2
3, // nzElementType_Double3
4, // nzElementType_Double4
1, // nzElementType_Float1
2, // nzElementType_Float2
3, // nzElementType_Float3
4 // nzElementType_Float4
4, // nzAttributeType_Color
1, // nzAttributeType_Double1
2, // nzAttributeType_Double2
3, // nzAttributeType_Double3
4, // nzAttributeType_Double4
1, // nzAttributeType_Float1
2, // nzAttributeType_Float2
3, // nzAttributeType_Float3
4 // nzAttributeType_Float4
};
const unsigned int elementSize[] =
unsigned int attributeStride[nzAttributeType_Max+1] =
{
4*sizeof(nzUInt8), // nzElementType_Color
1*sizeof(double), // nzElementType_Double1
2*sizeof(double), // nzElementType_Double2
3*sizeof(double), // nzElementType_Double3
4*sizeof(double), // nzElementType_Double4
1*sizeof(float), // nzElementType_Float1
2*sizeof(float), // nzElementType_Float2
3*sizeof(float), // nzElementType_Float3
4*sizeof(float) // nzElementType_Float4
4*sizeof(nzUInt8), // nzAttributeType_Color
1*sizeof(double), // nzAttributeType_Double1
2*sizeof(double), // nzAttributeType_Double2
3*sizeof(double), // nzAttributeType_Double3
4*sizeof(double), // nzAttributeType_Double4
1*sizeof(float), // nzAttributeType_Float1
2*sizeof(float), // nzAttributeType_Float2
3*sizeof(float), // nzAttributeType_Float3
4*sizeof(float) // nzAttributeType_Float4
};
bool VertexElementCompare(const NzVertexElement& elementA, const NzVertexElement& elementB)
{
// Nous classons d'abord par stream
if (elementA.stream == elementB.stream)
{
// Ensuite par usage
if (elementA.usage == elementB.usage)
// Et finalement par usageIndex
return elementA.usageIndex < elementB.usageIndex;
else
return elementA.usage < elementB.usage;
}
else
return elementA.stream < elementB.stream;
}
}
struct NzVertexDeclarationImpl
NzVertexDeclaration::NzVertexDeclaration() :
m_stride(0)
{
NzVertexDeclarationImpl() :
refCount(1)
{
}
}
std::vector<NzVertexElement> elements;
int elementPos[nzElementStream_Max+1][nzElementUsage_Max+1];
int streamPos[nzElementStream_Max+1];
unsigned int stride[nzElementStream_Max+1] = {0};
NzVertexDeclaration::NzVertexDeclaration(NzVertexDeclaration& declaration) :
NzResource(),
m_stride(declaration.m_stride)
{
std::memcpy(m_attributes, declaration.m_attributes, sizeof(Attribute)*(nzAttributeUsage_Max+1));
}
std::atomic_ushort refCount;
};
NzVertexDeclaration::NzVertexDeclaration(const NzVertexElement* elements, unsigned int elementCount)
void NzVertexDeclaration::DisableAttribute(nzAttributeUsage usage)
{
#ifdef NAZARA_DEBUG
if (!Create(elements, elementCount))
if (usage > nzAttributeUsage_Max)
{
NazaraError("Failed to create declaration");
throw std::runtime_error("Constructor failed");
}
#else
Create(elements, elementCount);
#endif
}
NzVertexDeclaration::NzVertexDeclaration(const NzVertexDeclaration& declaration) :
NzResource(),
m_sharedImpl(declaration.m_sharedImpl)
{
if (m_sharedImpl)
m_sharedImpl->refCount++;
}
NzVertexDeclaration::NzVertexDeclaration(NzVertexDeclaration&& declaration) noexcept :
m_sharedImpl(declaration.m_sharedImpl)
{
declaration.m_sharedImpl = nullptr;
}
NzVertexDeclaration::~NzVertexDeclaration()
{
Destroy();
}
bool NzVertexDeclaration::Create(const NzVertexElement* elements, unsigned int elementCount)
{
Destroy();
#if NAZARA_UTILITY_SAFE
if (!elements || elementCount == 0)
{
NazaraError("No element");
return false;
}
#endif
NzVertexDeclarationImpl* impl = new NzVertexDeclarationImpl;
std::memset(&impl->elementPos, -1, (nzElementStream_Max+1)*(nzElementUsage_Max+1)*sizeof(int));
std::memset(&impl->streamPos, -1, (nzElementStream_Max+1)*sizeof(int));
// On copie et trions les éléments
impl->elements.resize(elementCount);
std::memcpy(&impl->elements[0], elements, elementCount*sizeof(NzVertexElement));
std::sort(impl->elements.begin(), impl->elements.end(), VertexElementCompare);
for (unsigned int i = 0; i < elementCount; ++i)
{
NzVertexElement& current = impl->elements[i];
#if NAZARA_UTILITY_SAFE
// Notre tableau étant trié, s'il y a collision, les deux éléments identiques se suivent...
if (i > 0)
{
NzVertexElement& previous = impl->elements[i-1]; // On accède à l'élément précédent
if (previous.usage == current.usage && previous.usageIndex == current.usageIndex && previous.stream == current.stream)
{
// Les deux éléments sont identiques là où ils ne devraient pas, nous avons une collision...
NazaraError("Element usage 0x" + NzString::Number(current.usage, 16) + " collision with usage index " + NzString::Number(current.usageIndex) + " on stream 0x" + NzString::Number(current.stream, 16));
delete impl;
return false;
}
}
#endif
if (current.usageIndex == 0)
impl->elementPos[current.stream][current.usage] = i;
if (impl->streamPos[current.stream] == -1)
impl->streamPos[current.stream] = i; // Premier élément du stream (via le triage)
impl->stride[current.stream] += elementSize[current.type];
}
#if NAZARA_UTILITY_FORCE_DECLARATION_STRIDE_MULTIPLE_OF_32
for (unsigned int& stride : impl->stride)
stride = ((static_cast<int>(stride)-1)/32+1)*32;
#endif
m_sharedImpl = impl;
NotifyCreated();
return true;
}
void NzVertexDeclaration::Destroy()
{
if (!m_sharedImpl)
NazaraError("Attribute usage out of enum");
return;
NotifyDestroy();
if (--m_sharedImpl->refCount == 0)
delete m_sharedImpl;
m_sharedImpl = nullptr;
}
const NzVertexElement* NzVertexDeclaration::GetElement(unsigned int i) const
{
#if NAZARA_UTILITY_SAFE
if (!m_sharedImpl)
{
NazaraError("Declaration not created");
return nullptr;
}
if (i >= m_sharedImpl->elements.size())
{
NazaraError("Element index out of range (" + NzString::Number(i) + " >= " + NzString::Number(m_sharedImpl->elements.size()) + ')');
return nullptr;
}
#endif
return &m_sharedImpl->elements[i];
Attribute& attribute = m_attributes[usage];
if (attribute.enabled)
{
attribute.enabled = false;
m_stride -= attributeStride[attribute.type];
}
}
const NzVertexElement* NzVertexDeclaration::GetElement(nzElementStream stream, unsigned int i) const
void NzVertexDeclaration::EnableAttribute(nzAttributeUsage usage, nzAttributeType type, unsigned int offset)
{
#if NAZARA_UTILITY_SAFE
if (!m_sharedImpl)
#ifdef NAZARA_DEBUG
if (usage > nzAttributeUsage_Max)
{
NazaraError("Declaration not created");
return nullptr;
}
int streamPos = m_sharedImpl->streamPos[stream];
if (streamPos == -1)
{
NazaraError("Declaration has no stream 0x" + NzString::Number(stream, 16));
return nullptr;
}
unsigned int upperLimit = GetElementCount(stream);
if (i >= upperLimit)
{
NazaraError("Element index out of range (" + NzString::Number(i) + " >= " + NzString::Number(upperLimit) + ')');
return nullptr;
NazaraError("Attribute usage out of enum");
return;
}
#endif
return &m_sharedImpl->elements[m_sharedImpl->streamPos[stream]+i];
}
Attribute& attribute = m_attributes[usage];
const NzVertexElement* NzVertexDeclaration::GetElement(nzElementStream stream, nzElementUsage usage, unsigned int usageIndex) const
{
#if NAZARA_UTILITY_SAFE
if (!m_sharedImpl)
{
NazaraError("Declaration not created");
return nullptr;
}
#endif
int elementPos = m_sharedImpl->elementPos[stream][usage];
if (elementPos == -1)
return nullptr;
if (usageIndex == 0) // Si l'usage index vaut zéro, alors nous sommes certains d'être sur le bon élément (Majorité des cas)
return &m_sharedImpl->elements[elementPos];
if (attribute.enabled)
m_stride -= attributeStride[attribute.type];
else
{
elementPos += usageIndex;
if (static_cast<unsigned int>(elementPos) >= m_sharedImpl->elements.size())
return nullptr;
attribute.enabled = true;
NzVertexElement& element = m_sharedImpl->elements[elementPos];
if (element.stream != stream || element.usage != usage || element.usageIndex != usageIndex)
return nullptr;
attribute.offset = offset;
attribute.type = type;
return &element;
}
m_stride += attributeStride[type];
}
unsigned int NzVertexDeclaration::GetElementCount() const
void NzVertexDeclaration::GetAttribute(nzAttributeUsage usage, bool* enabled, nzAttributeType* type, unsigned int* offset) const
{
#if NAZARA_UTILITY_SAFE
if (!m_sharedImpl)
#ifdef NAZARA_DEBUG
if (usage > nzAttributeUsage_Max)
{
NazaraError("Declaration not created");
return 0;
NazaraError("Attribute usage out of enum");
return;
}
#endif
return m_sharedImpl->elements.size();
const Attribute& attribute = m_attributes[usage];
if (enabled)
*enabled = attribute.enabled;
if (type)
*type = attribute.type;
if (offset)
*offset = attribute.offset;
}
unsigned int NzVertexDeclaration::GetElementCount(nzElementStream stream) const
unsigned int NzVertexDeclaration::GetStride() const
{
#if NAZARA_UTILITY_SAFE
if (!m_sharedImpl)
{
NazaraError("Declaration not created");
return 0;
}
#endif
int streamPos = m_sharedImpl->streamPos[stream];
if (streamPos == -1)
return 0;
unsigned int upperLimit = 0;
if (stream == nzElementStream_Max)
upperLimit = m_sharedImpl->elements.size();
else
{
for (unsigned int upperStream = stream+1; upperStream <= nzElementStream_Max; ++upperStream)
{
if (m_sharedImpl->streamPos[upperStream] != -1)
{
upperLimit = m_sharedImpl->streamPos[upperStream];
break;
}
else if (upperStream == nzElementStream_Max) // Dernier stream, toujours pas de limite
upperLimit = m_sharedImpl->elements.size();
}
}
return upperLimit-streamPos;
return m_stride;
}
unsigned int NzVertexDeclaration::GetStride(nzElementStream stream) const
void NzVertexDeclaration::SetStride(unsigned int stride)
{
#if NAZARA_UTILITY_SAFE
if (!m_sharedImpl)
{
NazaraError("Declaration not created");
return 0;
}
#endif
return m_sharedImpl->stride[stream];
}
bool NzVertexDeclaration::HasElement(unsigned int i) const
{
return i < m_sharedImpl->elements.size();
}
bool NzVertexDeclaration::HasElement(nzElementStream stream, unsigned int i) const
{
return i < GetElementCount(stream);
}
bool NzVertexDeclaration::HasElement(nzElementStream stream, nzElementUsage usage, unsigned int usageIndex) const
{
int elementPos = m_sharedImpl->elementPos[stream][usage];
if (elementPos == -1)
return false;
elementPos += usageIndex;
if (static_cast<unsigned int>(elementPos) >= m_sharedImpl->elements.size())
return false;
NzVertexElement& element = m_sharedImpl->elements[elementPos];
if (element.stream != stream || element.usage != usage || element.usageIndex != usageIndex)
return false;
return true;
}
bool NzVertexDeclaration::HasStream(nzElementStream stream) const
{
#if NAZARA_UTILITY_SAFE
if (!m_sharedImpl)
{
NazaraError("Declaration not created");
return false;
}
#endif
return m_sharedImpl->streamPos[stream] != -1;
}
bool NzVertexDeclaration::IsValid() const
{
return m_sharedImpl != nullptr;
m_stride = stride;
}
NzVertexDeclaration& NzVertexDeclaration::operator=(const NzVertexDeclaration& declaration)
{
Destroy();
m_sharedImpl = declaration.m_sharedImpl;
if (m_sharedImpl)
m_sharedImpl->refCount++;
std::memcpy(m_attributes, declaration.m_attributes, sizeof(Attribute)*(nzAttributeUsage_Max+1));
m_stride = declaration.m_stride;
return *this;
}
NzVertexDeclaration& NzVertexDeclaration::operator=(NzVertexDeclaration&& declaration) noexcept
NzVertexDeclaration* NzVertexDeclaration::Get(nzVertexLayout layout)
{
Destroy();
#ifdef NAZARA_DEBUG
if (layout > nzVertexLayout_Max)
{
NazaraError("Vertex layout out of enum");
return nullptr;
}
#endif
m_sharedImpl = declaration.m_sharedImpl;
declaration.m_sharedImpl = nullptr;
return *this;
return &s_declarations[layout];
}
unsigned int NzVertexDeclaration::GetElementCount(nzElementType type)
unsigned int NzVertexDeclaration::GetAttributeSize(nzAttributeType type)
{
return elementCount[type];
#ifdef NAZARA_DEBUG
if (type > nzAttributeType_Max)
{
NazaraError("Attribute type out of enum");
return 0;
}
#endif
return attributeSize[type];
}
unsigned int NzVertexDeclaration::GetElementSize(nzElementType type)
bool NzVertexDeclaration::Initialize()
{
return elementSize[type];
s_declarations[nzVertexLayout_XY].EnableAttribute(nzAttributeUsage_Position, nzAttributeType_Float2, 0);
s_declarations[nzVertexLayout_XY_UV].EnableAttribute(nzAttributeUsage_Position, nzAttributeType_Float2, 0);
s_declarations[nzVertexLayout_XY_UV].EnableAttribute(nzAttributeUsage_TexCoord, nzAttributeType_Float2, 2*sizeof(float));
s_declarations[nzVertexLayout_XYZ].EnableAttribute(nzAttributeUsage_Position, nzAttributeType_Float3, 0);
s_declarations[nzVertexLayout_XYZ_Normal].EnableAttribute(nzAttributeUsage_Position, nzAttributeType_Float3, 0);
s_declarations[nzVertexLayout_XYZ_Normal].EnableAttribute(nzAttributeUsage_Normal, nzAttributeType_Float3, 3*sizeof(float));
s_declarations[nzVertexLayout_XYZ_Normal_UV].EnableAttribute(nzAttributeUsage_Position, nzAttributeType_Float3, 0);
s_declarations[nzVertexLayout_XYZ_Normal_UV].EnableAttribute(nzAttributeUsage_Normal, nzAttributeType_Float3, 3*sizeof(float));
s_declarations[nzVertexLayout_XYZ_Normal_UV].EnableAttribute(nzAttributeUsage_TexCoord, nzAttributeType_Float2, (3+3)*sizeof(float));
s_declarations[nzVertexLayout_XYZ_Normal_UV_Tangent].EnableAttribute(nzAttributeUsage_Position, nzAttributeType_Float3, 0);
s_declarations[nzVertexLayout_XYZ_Normal_UV_Tangent].EnableAttribute(nzAttributeUsage_Normal, nzAttributeType_Float3, 3*sizeof(float));
s_declarations[nzVertexLayout_XYZ_Normal_UV_Tangent].EnableAttribute(nzAttributeUsage_TexCoord, nzAttributeType_Float2, (3+3)*sizeof(float));
s_declarations[nzVertexLayout_XYZ_Normal_UV_Tangent].EnableAttribute(nzAttributeUsage_Tangent, nzAttributeType_Float3, (3+3+2)*sizeof(float));
s_declarations[nzVertexLayout_XYZ_UV].EnableAttribute(nzAttributeUsage_Position, nzAttributeType_Float3, 0);
s_declarations[nzVertexLayout_XYZ_UV].EnableAttribute(nzAttributeUsage_TexCoord, nzAttributeType_Float2, 3*sizeof(float));
s_declarations[nzVertexLayout_Matrix4].EnableAttribute(nzAttributeUsage_InstanceData0, nzAttributeType_Float4, 0*4*sizeof(float));
s_declarations[nzVertexLayout_Matrix4].EnableAttribute(nzAttributeUsage_InstanceData1, nzAttributeType_Float4, 1*4*sizeof(float));
s_declarations[nzVertexLayout_Matrix4].EnableAttribute(nzAttributeUsage_InstanceData2, nzAttributeType_Float4, 2*4*sizeof(float));
s_declarations[nzVertexLayout_Matrix4].EnableAttribute(nzAttributeUsage_InstanceData3, nzAttributeType_Float4, 3*4*sizeof(float));
return true;
}
void NzVertexDeclaration::Uninitialize()
{
}
NzVertexDeclaration NzVertexDeclaration::s_declarations[nzVertexLayout_Max+1];