Browse Source

python: support also normalized VertexFormat values.

They're unpacked to full floats on element access and packed back from
full floats on mutable access, which makes this all very nice and
transparent. Yay Python!

That's it for now, I'll postpone half-float and matrix types for later
when these are actually needed, as it needs extra testing for the
aligned variants too.
next
Vladimír Vondruš 3 years ago
parent
commit
d62b44e3cd
  1. 7
      doc/python/magnum.trade.rst
  2. 17
      src/python/magnum/test/test_trade.py
  3. 32
      src/python/magnum/trade.cpp

7
doc/python/magnum.trade.rst

@ -119,6 +119,13 @@
:ref:`mutable_indices` and :ref:`mutable_attribute()`, for example to
perform a static transformation of the mesh before passing it to OpenGL.
Normalized formats (such as :ref:`VertexFormat.VECTOR3UB_NORMALIZED`) are
unpacked to a corresponding floating-point representation in element access
and packed from a floating-point representation in mutable acess. The type
annotation is however still matching the original type (such as :py:`'3B'`
in this case), so code consuming these via the buffer protocol needs to
handle the normalization explicitly if needed.
.. py:property:: magnum.trade.MeshData.mutable_index_data
:raise AttributeError: If :ref:`index_data_flags` doesn't contain
:ref:`DataFlag.MUTABLE`

17
src/python/magnum/test/test_trade.py

@ -461,6 +461,23 @@ class MeshData(unittest.TestCase):
mutable_packed[1] -= Vector3i(12, 56, 200)
self.assertEqual(packed[1], Vector3(39, 46, 55))
def test_normalized_attribute_access(self):
importer = trade.ImporterManager().load_and_instantiate('GltfImporter')
importer.open_file(os.path.join(os.path.dirname(__file__), 'mesh.gltf'))
mesh = importer.mesh(0)
self.assertEqual(mesh.index_data_flags, trade.DataFlag.OWNED|trade.DataFlag.MUTABLE)
self.assertEqual(mesh.attribute_format(trade.MeshAttribute.COLOR), VertexFormat.VECTOR3UB_NORMALIZED)
normalized = mesh.attribute(trade.MeshAttribute.COLOR)
mutable_normalized = mesh.mutable_attribute(trade.MeshAttribute.COLOR)
self.assertEqual(normalized[1], Vector3(0.2, 0.4, 1))
self.assertEqual(mutable_normalized[1], Vector3(0.2, 0.4, 1))
mutable_normalized[1] *= 0.5
# Rounding errors are expected
self.assertEqual(normalized[1], Vector3(0.101961, 0.2, 0.501961))
def test_data_access_not_mutable(self):
mesh = primitives.cube_solid()
# TODO split this once there's a mesh where only one or the other would

32
src/python/magnum/trade.cpp

@ -29,8 +29,8 @@
#include <Corrade/Containers/StringStl.h> /** @todo drop once we have our string casters */
#include <Corrade/Containers/Triple.h>
#include <Magnum/ImageView.h>
#include <Magnum/Math/Half.h>
#include <Magnum/Math/Matrix4.h>
#include <Magnum/Math/Packing.h>
#include <Magnum/Trade/AbstractImporter.h>
#include <Magnum/Trade/AbstractImageConverter.h>
#include <Magnum/Trade/AbstractSceneConverter.h>
@ -489,47 +489,75 @@ Containers::Triple<const char*, py::object(*)(const char*), void(*)(char*, py::h
[](char* item, py::handle object) { \
*reinterpret_cast<format*>(item) = format(py::cast<castType>(object)); \
}};
/* Normalized types that need to be packed/unpacked before passed
from/to pybind */
#define _cNormalized(format, unpackType) \
case VertexFormat::format ## Normalized: return { \
Containers::Implementation::pythonFormatString<format>(), \
[](const char* item) { \
return py::cast(Math::unpack<unpackType>(*reinterpret_cast<const format*>(item))); \
}, \
[](char* item, py::handle object) { \
*reinterpret_cast<format*>(item) = Math::pack<format>(py::cast<unpackType>(object)); \
}};
/* LCOV_EXCL_START */
_c(Float)
_c(Double)
_c(UnsignedByte)
_cNormalized(UnsignedByte, Float)
_c(Byte)
_cNormalized(Byte, Float)
_c(UnsignedShort)
_cNormalized(UnsignedShort, Float)
_c(Short)
_cNormalized(Short, Float)
_c(UnsignedInt)
_c(Int)
_c(Vector2)
_c(Vector2d)
_cc(Vector2ub, Vector2ui)
_cNormalized(Vector2ub, Vector2)
_cc(Vector2b, Vector2i)
_cNormalized(Vector2b, Vector2)
_cc(Vector2us, Vector2ui)
_cNormalized(Vector2us, Vector2)
_cc(Vector2s, Vector2i)
_cNormalized(Vector2s, Vector2)
_c(Vector2ui)
_c(Vector2i)
_c(Vector3)
_c(Vector3d)
_cc(Vector3ub, Vector3ui)
_cNormalized(Vector3ub, Vector3)
_cc(Vector3b, Vector3i)
_cNormalized(Vector3b, Vector3)
_cc(Vector3us, Vector3ui)
_cNormalized(Vector3us, Vector3)
_cc(Vector3s, Vector3i)
_cNormalized(Vector3s, Vector3)
_c(Vector3ui)
_c(Vector3i)
_c(Vector4)
_c(Vector4d)
_cc(Vector4ub, Vector4ui)
_cNormalized(Vector4ub, Vector4)
_cc(Vector4b, Vector4i)
_cNormalized(Vector4b, Vector4)
_cc(Vector4us, Vector4ui)
_cNormalized(Vector4us, Vector4)
_cc(Vector4s, Vector4i)
_cNormalized(Vector4s, Vector4)
_c(Vector4ui)
_c(Vector4i)
/* LCOV_EXCL_STOP */
#undef _c
#undef _cc
#undef _cNormalized
/** @todo handle half, normalized and matrix types */
/** @todo handle half and matrix types */
default:
return {};
}

Loading…
Cancel
Save