Browse Source

MeshTools: generateSmoothNormals() taking also type-erased indices.

pull/371/head
Vladimír Vondruš 6 years ago
parent
commit
aeedf1264d
  1. 3
      doc/changelog.dox
  2. 18
      src/Magnum/MeshTools/GenerateNormals.cpp
  3. 23
      src/Magnum/MeshTools/GenerateNormals.h
  4. 51
      src/Magnum/MeshTools/Test/GenerateNormalsTest.cpp

3
doc/changelog.dox

@ -212,6 +212,9 @@ See also:
@ref MeshTools::removeDuplicatesInPlace() variant
- Added @ref MeshTools::duplicateInto() variants that take type-erased
2D strided array views
- Added @ref MeshTools::generateSmoothNormals() and
@ref MeshTools::generateSmoothNormalsInto() variants taking type-erased
index arrays
@subsubsection changelog-latest-changes-platform Platform libraries

18
src/Magnum/MeshTools/GenerateNormals.cpp

@ -234,6 +234,18 @@ void generateSmoothNormalsInto(const Containers::StridedArrayView1D<const Unsign
generateSmoothNormalsIntoImplementation(indices, positions, normals);
}
void generateSmoothNormalsInto(const Containers::StridedArrayView2D<const char>& indices, const Containers::StridedArrayView1D<const Vector3>& positions, const Containers::StridedArrayView1D<Vector3>& normals) {
CORRADE_ASSERT(indices.isContiguous<1>(), "MeshTools::generateSmoothNormalsInto(): second index view dimension is not contiguous", );
if(indices.size()[1] == 4)
return generateSmoothNormalsIntoImplementation(Containers::arrayCast<1, const UnsignedInt>(indices), positions, normals);
else if(indices.size()[1] == 2)
return generateSmoothNormalsIntoImplementation(Containers::arrayCast<1, const UnsignedShort>(indices), positions, normals);
else {
CORRADE_ASSERT(indices.size()[1] == 1, "MeshTools::generateSmoothNormalsInto(): expected index type size 1, 2 or 4 but got" << indices.size()[1], );
return generateSmoothNormalsIntoImplementation(Containers::arrayCast<1, const UnsignedByte>(indices), positions, normals);
}
}
namespace {
template<class T> inline Containers::Array<Vector3> generateSmoothNormalsImplementation(const Containers::StridedArrayView1D<const T>& indices, const Containers::StridedArrayView1D<const Vector3>& positions) {
@ -257,4 +269,10 @@ Containers::Array<Vector3> generateSmoothNormals(const Containers::StridedArrayV
return generateSmoothNormalsImplementation(indices, positions);
}
Containers::Array<Vector3> generateSmoothNormals(const Containers::StridedArrayView2D<const char>& indices, const Containers::StridedArrayView1D<const Vector3>& positions) {
Containers::Array<Vector3> out{Containers::NoInit, positions.size()};
generateSmoothNormalsInto(indices, positions, out);
return out;
}
}}

23
src/Magnum/MeshTools/GenerateNormals.h

@ -132,6 +132,17 @@ MAGNUM_MESHTOOLS_EXPORT Containers::Array<Vector3> generateSmoothNormals(const C
*/
MAGNUM_MESHTOOLS_EXPORT Containers::Array<Vector3> generateSmoothNormals(const Containers::StridedArrayView1D<const UnsignedByte>& indices, const Containers::StridedArrayView1D<const Vector3>& positions);
/**
@brief Generate smooth normals using a type-erased index array
@m_since_latest
Expects that the second dimension of @p indices is contiguous and represents
the actual 1/2/4-byte index type. Based on its size then calls one of the
@ref generateSmoothNormals(const Containers::StridedArrayView1D<const UnsignedInt>&, const Containers::StridedArrayView1D<const Vector3>&)
etc. overloads.
*/
MAGNUM_MESHTOOLS_EXPORT Containers::Array<Vector3> generateSmoothNormals(const Containers::StridedArrayView2D<const char>& indices, const Containers::StridedArrayView1D<const Vector3>& positions);
/**
@brief Generate smooth normals into an existing array
@param[in] indices Triangle face indices
@ -167,6 +178,18 @@ MAGNUM_MESHTOOLS_EXPORT void generateSmoothNormalsInto(const Containers::Strided
*/
MAGNUM_MESHTOOLS_EXPORT void generateSmoothNormalsInto(const Containers::StridedArrayView1D<const UnsignedByte>& indices, const Containers::StridedArrayView1D<const Vector3>& positions, const Containers::StridedArrayView1D<Vector3>& normals);
/**
@brief Generate smooth normals into an existing array using a type-erased index array
@m_since_latest
Expects that @p normals has the same size as @p positions and that the second
dimension of @p indices is contiguous and represents the actual 1/2/4-byte
index type. Based on its size then calls one of the
@ref generateSmoothNormalsInto(const Containers::StridedArrayView1D<const UnsignedInt>&, const Containers::StridedArrayView1D<const Vector3>&, const Containers::StridedArrayView1D<Vector3>&)
etc. overloads.
*/
MAGNUM_MESHTOOLS_EXPORT void generateSmoothNormalsInto(const Containers::StridedArrayView2D<const char>& indices, const Containers::StridedArrayView1D<const Vector3>& positions, const Containers::StridedArrayView1D<Vector3>& normals);
}}
#endif

51
src/Magnum/MeshTools/Test/GenerateNormalsTest.cpp

@ -61,6 +61,10 @@ struct GenerateNormalsTest: TestSuite::Tester {
void smoothOutOfBounds();
void smoothIntoWrongSize();
template<class T> void smoothErased();
void smoothErasedNonContiguous();
void smoothErasedWrongIndexSize();
void benchmarkFlat();
void benchmarkSmooth();
};
@ -83,7 +87,13 @@ GenerateNormalsTest::GenerateNormalsTest() {
&GenerateNormalsTest::smoothNanPosition,
&GenerateNormalsTest::smoothWrongCount,
&GenerateNormalsTest::smoothOutOfBounds,
&GenerateNormalsTest::smoothIntoWrongSize});
&GenerateNormalsTest::smoothIntoWrongSize,
&GenerateNormalsTest::smoothErased<UnsignedByte>,
&GenerateNormalsTest::smoothErased<UnsignedShort>,
&GenerateNormalsTest::smoothErased<UnsignedInt>,
&GenerateNormalsTest::smoothErasedNonContiguous,
&GenerateNormalsTest::smoothErasedWrongIndexSize});
addBenchmarks({&GenerateNormalsTest::benchmarkFlat,
&GenerateNormalsTest::benchmarkSmooth}, 150);
@ -425,6 +435,45 @@ void GenerateNormalsTest::benchmarkSmooth() {
CORRADE_COMPARE(Math::min(normals), (Vector3{-0.996072f, -0.997808f, -0.996072f}));
}
template<class T> void GenerateNormalsTest::smoothErased() {
setTestCaseTemplateName(Math::TypeTraits<T>::name());
const T indices[]{0, 1, 2, 3, 4, 5};
/* Should generate the same output as flat normals */
CORRADE_COMPARE_AS(generateSmoothNormals(Containers::arrayCast<2, const char>(Containers::stridedArrayView(indices)), TwoTriangles),
Containers::arrayView<Vector3>({
Vector3::zAxis(),
Vector3::zAxis(),
Vector3::zAxis(),
-Vector3::zAxis(),
-Vector3::zAxis(),
-Vector3::zAxis()
}), TestSuite::Compare::Container);
}
void GenerateNormalsTest::smoothErasedNonContiguous() {
const char indices[6*4]{};
const Vector3 positions[3];
std::stringstream out;
Error redirectError{&out};
generateSmoothNormals(Containers::StridedArrayView2D<const char>{indices, {6, 2}, {4, 2}}, positions);
CORRADE_COMPARE(out.str(),
"MeshTools::generateSmoothNormalsInto(): second index view dimension is not contiguous\n");
}
void GenerateNormalsTest::smoothErasedWrongIndexSize() {
const char indices[6*3]{};
const Vector3 positions[3];
std::stringstream out;
Error redirectError{&out};
generateSmoothNormals(Containers::StridedArrayView2D<const char>{indices, {6, 3}}.every(2), positions);
CORRADE_COMPARE(out.str(),
"MeshTools::generateSmoothNormalsInto(): expected index type size 1, 2 or 4 but got 3\n");
}
}}}}
CORRADE_TEST_MAIN(Magnum::MeshTools::Test::GenerateNormalsTest)

Loading…
Cancel
Save