|
|
|
|
@ -52,82 +52,6 @@
|
|
|
|
|
|
|
|
|
|
namespace Magnum { namespace MeshTools { |
|
|
|
|
|
|
|
|
|
GL::Mesh compile(const Trade::MeshData& meshData, CompileFlags flags) { |
|
|
|
|
/* If we want to generate normals, prepare a new mesh data and recurse,
|
|
|
|
|
with the flags unset */ |
|
|
|
|
if(meshData.primitive() == MeshPrimitive::Triangles && (flags & (CompileFlag::GenerateFlatNormals|CompileFlag::GenerateSmoothNormals))) { |
|
|
|
|
CORRADE_ASSERT(meshData.attributeCount(Trade::MeshAttribute::Position), |
|
|
|
|
"MeshTools::compile(): the mesh has no positions, can't generate normals", GL::Mesh{}); |
|
|
|
|
/* This could fire if we have 2D positions or for packed formats */ |
|
|
|
|
CORRADE_ASSERT(meshData.attributeFormat(Trade::MeshAttribute::Position) == VertexFormat::Vector3, |
|
|
|
|
"MeshTools::compile(): can't generate normals for" << meshData.attributeFormat(Trade::MeshAttribute::Position) << "positions", GL::Mesh{}); |
|
|
|
|
|
|
|
|
|
/* If the data already have a normal array, reuse its location,
|
|
|
|
|
otherwise mix in an extra one */ |
|
|
|
|
Trade::MeshAttributeData normalAttribute; |
|
|
|
|
Containers::ArrayView<const Trade::MeshAttributeData> extra; |
|
|
|
|
if(!meshData.hasAttribute(Trade::MeshAttribute::Normal)) { |
|
|
|
|
normalAttribute = Trade::MeshAttributeData{ |
|
|
|
|
Trade::MeshAttribute::Normal, VertexFormat::Vector3, |
|
|
|
|
nullptr}; |
|
|
|
|
extra = {&normalAttribute, 1}; |
|
|
|
|
/* If we reuse a normal location, expect correct type */ |
|
|
|
|
} else CORRADE_ASSERT(meshData.attributeFormat(Trade::MeshAttribute::Normal) == VertexFormat::Vector3, |
|
|
|
|
"MeshTools::compile(): can't generate normals into" << meshData.attributeFormat(Trade::MeshAttribute::Normal), GL::Mesh{}); |
|
|
|
|
|
|
|
|
|
/* If we want flat normals, we need to first duplicate everything using
|
|
|
|
|
the index buffer. Otherwise just interleave the potential extra |
|
|
|
|
normal attribute in. */ |
|
|
|
|
Trade::MeshData generated{MeshPrimitive::Points, 0}; |
|
|
|
|
if(flags & CompileFlag::GenerateFlatNormals && meshData.isIndexed()) |
|
|
|
|
generated = duplicate(meshData, extra); |
|
|
|
|
else |
|
|
|
|
generated = interleave(meshData, extra); |
|
|
|
|
|
|
|
|
|
/* Generate the normals. If we don't have the index buffer, we can only
|
|
|
|
|
generate flat ones. */ |
|
|
|
|
if(flags & CompileFlag::GenerateFlatNormals || !meshData.isIndexed()) |
|
|
|
|
generateFlatNormalsInto( |
|
|
|
|
generated.attribute<Vector3>(Trade::MeshAttribute::Position), |
|
|
|
|
generated.mutableAttribute<Vector3>(Trade::MeshAttribute::Normal)); |
|
|
|
|
else |
|
|
|
|
generateSmoothNormalsInto(generated.indices(), |
|
|
|
|
generated.attribute<Vector3>(Trade::MeshAttribute::Position), |
|
|
|
|
generated.mutableAttribute<Vector3>(Trade::MeshAttribute::Normal)); |
|
|
|
|
|
|
|
|
|
return compile(generated, flags & ~(CompileFlag::GenerateFlatNormals|CompileFlag::GenerateSmoothNormals)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
flags &= ~(CompileFlag::GenerateFlatNormals|CompileFlag::GenerateSmoothNormals); |
|
|
|
|
CORRADE_INTERNAL_ASSERT(!flags); |
|
|
|
|
return compile(meshData); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
GL::Mesh compile(const Trade::MeshData& meshData) { |
|
|
|
|
GL::Buffer indices{NoCreate}; |
|
|
|
|
if(meshData.isIndexed()) { |
|
|
|
|
indices = GL::Buffer{GL::Buffer::TargetHint::ElementArray}; |
|
|
|
|
indices.setData(meshData.indexData()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
GL::Buffer vertices{GL::Buffer::TargetHint::Array}; |
|
|
|
|
vertices.setData(meshData.vertexData()); |
|
|
|
|
|
|
|
|
|
return compile(meshData, std::move(indices), std::move(vertices)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
GL::Mesh compile(const Trade::MeshData& meshData, GL::Buffer& indices, GL::Buffer& vertices) { |
|
|
|
|
return compile(meshData, GL::Buffer::wrap(indices.id(), GL::Buffer::TargetHint::ElementArray), GL::Buffer::wrap(vertices.id(), GL::Buffer::TargetHint::Array)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
GL::Mesh compile(const Trade::MeshData& meshData, GL::Buffer& indices, GL::Buffer&& vertices) { |
|
|
|
|
return compile(meshData, GL::Buffer::wrap(indices.id(), GL::Buffer::TargetHint::ElementArray), std::move(vertices)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
GL::Mesh compile(const Trade::MeshData& meshData, GL::Buffer&& indices, GL::Buffer& vertices) { |
|
|
|
|
return compile(meshData, std::move(indices), GL::Buffer::wrap(vertices.id(), GL::Buffer::TargetHint::Array)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
GL::Mesh compile(const Trade::MeshData& meshData, GL::Buffer&& indices, GL::Buffer&& vertices) { |
|
|
|
|
CORRADE_ASSERT((!meshData.isIndexed() || indices.id()) && vertices.id(), |
|
|
|
|
"MeshTools::compile(): invalid external buffer(s)", GL::Mesh{}); |
|
|
|
|
@ -198,6 +122,82 @@ GL::Mesh compile(const Trade::MeshData& meshData, GL::Buffer&& indices, GL::Buff
|
|
|
|
|
return mesh; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
GL::Mesh compile(const Trade::MeshData& meshData) { |
|
|
|
|
GL::Buffer indices{NoCreate}; |
|
|
|
|
if(meshData.isIndexed()) { |
|
|
|
|
indices = GL::Buffer{GL::Buffer::TargetHint::ElementArray}; |
|
|
|
|
indices.setData(meshData.indexData()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
GL::Buffer vertices{GL::Buffer::TargetHint::Array}; |
|
|
|
|
vertices.setData(meshData.vertexData()); |
|
|
|
|
|
|
|
|
|
return compile(meshData, std::move(indices), std::move(vertices)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
GL::Mesh compile(const Trade::MeshData& meshData, GL::Buffer& indices, GL::Buffer& vertices) { |
|
|
|
|
return compile(meshData, GL::Buffer::wrap(indices.id(), GL::Buffer::TargetHint::ElementArray), GL::Buffer::wrap(vertices.id(), GL::Buffer::TargetHint::Array)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
GL::Mesh compile(const Trade::MeshData& meshData, GL::Buffer& indices, GL::Buffer&& vertices) { |
|
|
|
|
return compile(meshData, GL::Buffer::wrap(indices.id(), GL::Buffer::TargetHint::ElementArray), std::move(vertices)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
GL::Mesh compile(const Trade::MeshData& meshData, GL::Buffer&& indices, GL::Buffer& vertices) { |
|
|
|
|
return compile(meshData, std::move(indices), GL::Buffer::wrap(vertices.id(), GL::Buffer::TargetHint::Array)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
GL::Mesh compile(const Trade::MeshData& meshData, CompileFlags flags) { |
|
|
|
|
/* If we want to generate normals, prepare a new mesh data and recurse,
|
|
|
|
|
with the flags unset */ |
|
|
|
|
if(meshData.primitive() == MeshPrimitive::Triangles && (flags & (CompileFlag::GenerateFlatNormals|CompileFlag::GenerateSmoothNormals))) { |
|
|
|
|
CORRADE_ASSERT(meshData.attributeCount(Trade::MeshAttribute::Position), |
|
|
|
|
"MeshTools::compile(): the mesh has no positions, can't generate normals", GL::Mesh{}); |
|
|
|
|
/* This could fire if we have 2D positions or for packed formats */ |
|
|
|
|
CORRADE_ASSERT(meshData.attributeFormat(Trade::MeshAttribute::Position) == VertexFormat::Vector3, |
|
|
|
|
"MeshTools::compile(): can't generate normals for" << meshData.attributeFormat(Trade::MeshAttribute::Position) << "positions", GL::Mesh{}); |
|
|
|
|
|
|
|
|
|
/* If the data already have a normal array, reuse its location,
|
|
|
|
|
otherwise mix in an extra one */ |
|
|
|
|
Trade::MeshAttributeData normalAttribute; |
|
|
|
|
Containers::ArrayView<const Trade::MeshAttributeData> extra; |
|
|
|
|
if(!meshData.hasAttribute(Trade::MeshAttribute::Normal)) { |
|
|
|
|
normalAttribute = Trade::MeshAttributeData{ |
|
|
|
|
Trade::MeshAttribute::Normal, VertexFormat::Vector3, |
|
|
|
|
nullptr}; |
|
|
|
|
extra = {&normalAttribute, 1}; |
|
|
|
|
/* If we reuse a normal location, expect correct type */ |
|
|
|
|
} else CORRADE_ASSERT(meshData.attributeFormat(Trade::MeshAttribute::Normal) == VertexFormat::Vector3, |
|
|
|
|
"MeshTools::compile(): can't generate normals into" << meshData.attributeFormat(Trade::MeshAttribute::Normal), GL::Mesh{}); |
|
|
|
|
|
|
|
|
|
/* If we want flat normals, we need to first duplicate everything using
|
|
|
|
|
the index buffer. Otherwise just interleave the potential extra |
|
|
|
|
normal attribute in. */ |
|
|
|
|
Trade::MeshData generated{MeshPrimitive::Points, 0}; |
|
|
|
|
if(flags & CompileFlag::GenerateFlatNormals && meshData.isIndexed()) |
|
|
|
|
generated = duplicate(meshData, extra); |
|
|
|
|
else |
|
|
|
|
generated = interleave(meshData, extra); |
|
|
|
|
|
|
|
|
|
/* Generate the normals. If we don't have the index buffer, we can only
|
|
|
|
|
generate flat ones. */ |
|
|
|
|
if(flags & CompileFlag::GenerateFlatNormals || !meshData.isIndexed()) |
|
|
|
|
generateFlatNormalsInto( |
|
|
|
|
generated.attribute<Vector3>(Trade::MeshAttribute::Position), |
|
|
|
|
generated.mutableAttribute<Vector3>(Trade::MeshAttribute::Normal)); |
|
|
|
|
else |
|
|
|
|
generateSmoothNormalsInto(generated.indices(), |
|
|
|
|
generated.attribute<Vector3>(Trade::MeshAttribute::Position), |
|
|
|
|
generated.mutableAttribute<Vector3>(Trade::MeshAttribute::Normal)); |
|
|
|
|
|
|
|
|
|
return compile(generated, flags & ~(CompileFlag::GenerateFlatNormals|CompileFlag::GenerateSmoothNormals)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
flags &= ~(CompileFlag::GenerateFlatNormals|CompileFlag::GenerateSmoothNormals); |
|
|
|
|
CORRADE_INTERNAL_ASSERT(!flags); |
|
|
|
|
return compile(meshData); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#ifdef MAGNUM_BUILD_DEPRECATED |
|
|
|
|
CORRADE_IGNORE_DEPRECATED_PUSH |
|
|
|
|
GL::Mesh compile(const Trade::MeshData2D& meshData) { |
|
|
|
|
|