Browse Source

Trade: add SceneData::fooInto() overloads for subranges.

Useful for cases when it's desirable to extract just some elements, for
example just for a particular object ID. Or when allocating an
arbitrarily large array isn't wanted for perf/memory reasons.
pull/525/head
Vladimír Vondruš 5 years ago
parent
commit
4e8fa9d847
  1. 349
      src/Magnum/Trade/SceneData.cpp
  2. 155
      src/Magnum/Trade/SceneData.h
  3. 904
      src/Magnum/Trade/Test/SceneDataTest.cpp

349
src/Magnum/Trade/SceneData.cpp

@ -499,22 +499,32 @@ Containers::ArrayView<char> SceneData::mutableData() & {
return _data;
}
Containers::StridedArrayView1D<const void> SceneData::fieldDataObjectViewInternal(const SceneFieldData& field) const {
Containers::StridedArrayView1D<const void> SceneData::fieldDataObjectViewInternal(const SceneFieldData& field, const std::size_t offset, const std::size_t size) const {
CORRADE_INTERNAL_ASSERT(offset + size <= field._size);
return Containers::StridedArrayView1D<const void>{
/* We're *sure* the view is correct, so faking the view size */
/** @todo better ideas for the StridedArrayView API? */
{field._isOffsetOnly ? _data.data() + field._objectData.offset :
field._objectData.pointer, ~std::size_t{}},
field._size, field._objectStride};
{static_cast<const char*>(field._isOffsetOnly ?
_data.data() + field._objectData.offset : field._objectData.pointer)
+ field._fieldStride*offset, ~std::size_t{}},
size, field._objectStride};
}
Containers::StridedArrayView1D<const void> SceneData::fieldDataFieldViewInternal(const SceneFieldData& field) const {
Containers::StridedArrayView1D<const void> SceneData::fieldDataObjectViewInternal(const SceneFieldData& field) const {
return fieldDataObjectViewInternal(field, 0, field._size);
}
Containers::StridedArrayView1D<const void> SceneData::fieldDataFieldViewInternal(const SceneFieldData& field, const std::size_t offset, const std::size_t size) const {
CORRADE_INTERNAL_ASSERT(offset + size <= field._size);
return Containers::StridedArrayView1D<const void>{
/* We're *sure* the view is correct, so faking the view size */
/** @todo better ideas for the StridedArrayView API? */
{field._isOffsetOnly ? _data.data() + field._fieldData.offset :
field._fieldData.pointer, ~std::size_t{}},
field._size, field._fieldStride};
{static_cast<const char*>(field._isOffsetOnly ?
_data.data() + field._fieldData.offset : field._fieldData.pointer)
+ field._fieldStride*offset, ~std::size_t{}},
size, field._fieldStride};
}
Containers::StridedArrayView1D<const void> SceneData::fieldDataFieldViewInternal(const SceneFieldData& field) const {
return fieldDataFieldViewInternal(field, 0, field._size);
}
SceneFieldData SceneData::fieldData(const UnsignedInt id) const {
@ -668,13 +678,12 @@ Containers::StridedArrayView2D<char> SceneData::mutableField(const SceneField na
return mutableField(fieldId);
}
void SceneData::objectsInto(const UnsignedInt fieldId, const Containers::StridedArrayView1D<UnsignedInt>& destination) const {
CORRADE_ASSERT(fieldId < _fields.size(),
"Trade::SceneData::objectsInto(): index" << fieldId << "out of range for" << _fields.size() << "fields", );
void SceneData::objectsIntoInternal(const UnsignedInt fieldId, const std::size_t offset, const Containers::StridedArrayView1D<UnsignedInt>& destination) const {
/* fieldId, offset and destination.size() is assumed to be in bounds,
checked by the callers */
const SceneFieldData& field = _fields[fieldId];
CORRADE_ASSERT(destination.size() == field._size,
"Trade::SceneData::objectsInto(): expected a view with" << field._size << "elements but got" << destination.size(), );
const Containers::StridedArrayView1D<const void> objectData = fieldDataObjectViewInternal(field);
const Containers::StridedArrayView1D<const void> objectData = fieldDataObjectViewInternal(field, offset, destination.size());
const auto destination1ui = Containers::arrayCast<2, UnsignedInt>(destination);
if(field._objectType == SceneObjectType::UnsignedInt)
@ -689,13 +698,31 @@ void SceneData::objectsInto(const UnsignedInt fieldId, const Containers::Strided
} else CORRADE_INTERNAL_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */
}
void SceneData::objectsInto(const UnsignedInt fieldId, const Containers::StridedArrayView1D<UnsignedInt>& destination) const {
CORRADE_ASSERT(fieldId < _fields.size(),
"Trade::SceneData::objectsInto(): index" << fieldId << "out of range for" << _fields.size() << "fields", );
CORRADE_ASSERT(destination.size() == _fields[fieldId]._size,
"Trade::SceneData::objectsInto(): expected a view with" << _fields[fieldId]._size << "elements but got" << destination.size(), );
objectsIntoInternal(fieldId, 0, destination);
}
std::size_t SceneData::objectsInto(const UnsignedInt fieldId, const std::size_t offset, const Containers::StridedArrayView1D<UnsignedInt>& destination) const {
CORRADE_ASSERT(fieldId < _fields.size(),
"Trade::SceneData::objectsInto(): index" << fieldId << "out of range for" << _fields.size() << "fields", {});
CORRADE_ASSERT(offset <= _fields[fieldId]._size,
"Trade::SceneData::objectsInto(): offset" << offset << "out of bounds for a field of size" << _fields[fieldId]._size, {});
const std::size_t size = Math::min(destination.size(), std::size_t(_fields[fieldId]._size) - offset);
objectsIntoInternal(fieldId, offset, destination.prefix(size));
return size;
}
Containers::Array<UnsignedInt> SceneData::objectsAsArray(const UnsignedInt fieldId) const {
CORRADE_ASSERT(fieldId < _fields.size(),
/* Using the same message as in Into() to avoid too many redundant
strings in the binary */
"Trade::SceneData::objectsInto(): index" << fieldId << "out of range for" << _fields.size() << "fields", {});
Containers::Array<UnsignedInt> out{NoInit, std::size_t(_fields[fieldId]._size)};
objectsInto(fieldId, out);
objectsIntoInternal(fieldId, 0, out);
return out;
}
@ -706,6 +733,13 @@ void SceneData::objectsInto(const SceneField name, const Containers::StridedArra
objectsInto(fieldId, destination);
}
std::size_t SceneData::objectsInto(const SceneField name, std::size_t offset, const Containers::StridedArrayView1D<UnsignedInt>& destination) const {
const UnsignedInt fieldId = fieldFor(name);
CORRADE_ASSERT(fieldId != ~UnsignedInt{},
"Trade::SceneData::objectsInto(): field" << name << "not found", {});
return objectsInto(fieldId, offset, destination);
}
Containers::Array<UnsignedInt> SceneData::objectsAsArray(const SceneField name) const {
const UnsignedInt fieldId = fieldFor(name);
CORRADE_ASSERT(fieldId != ~UnsignedInt{},
@ -715,13 +749,12 @@ Containers::Array<UnsignedInt> SceneData::objectsAsArray(const SceneField name)
return objectsAsArray(fieldId);
}
void SceneData::parentsIntoInternal(const UnsignedInt fieldId, const Containers::StridedArrayView1D<Int>& destination) const {
CORRADE_ASSERT(fieldId != ~UnsignedInt{},
"Trade::SceneData::parentsInto(): field not found", );
void SceneData::parentsIntoInternal(const UnsignedInt fieldId, const std::size_t offset, const Containers::StridedArrayView1D<Int>& destination) const {
/* fieldId, offset and destination.size() is assumed to be in bounds,
checked by the callers */
const SceneFieldData& field = _fields[fieldId];
CORRADE_ASSERT(destination.size() == field._size,
"Trade::SceneData::parentsInto(): expected a view with" << field._size << "elements but got" << destination.size(), );
const Containers::StridedArrayView1D<const void> fieldData = fieldDataFieldViewInternal(field);
const Containers::StridedArrayView1D<const void> fieldData = fieldDataFieldViewInternal(field, offset, destination.size());
const auto destination1i = Containers::arrayCast<2, Int>(destination);
if(field._fieldType == SceneFieldType::Int)
@ -737,7 +770,23 @@ void SceneData::parentsIntoInternal(const UnsignedInt fieldId, const Containers:
}
void SceneData::parentsInto(const Containers::StridedArrayView1D<Int>& destination) const {
parentsIntoInternal(fieldFor(SceneField::Parent), destination);
const UnsignedInt fieldId = fieldFor(SceneField::Parent);
CORRADE_ASSERT(fieldId != ~UnsignedInt{},
"Trade::SceneData::parentsInto(): field not found", );
CORRADE_ASSERT(destination.size() == _fields[fieldId]._size,
"Trade::SceneData::parentsInto(): expected a view with" << _fields[fieldId]._size << "elements but got" << destination.size(), );
parentsIntoInternal(fieldId, 0, destination);
}
std::size_t SceneData::parentsInto(const std::size_t offset, const Containers::StridedArrayView1D<Int>& destination) const {
const UnsignedInt fieldId = fieldFor(SceneField::Parent);
CORRADE_ASSERT(fieldId != ~UnsignedInt{},
"Trade::SceneData::parentsInto(): field not found", {});
CORRADE_ASSERT(offset <= _fields[fieldId]._size,
"Trade::SceneData::parentsInto(): offset" << offset << "out of bounds for a field of size" << _fields[fieldId]._size, {});
const std::size_t size = Math::min(destination.size(), std::size_t(_fields[fieldId]._size) - offset);
parentsIntoInternal(fieldId, offset, destination.prefix(size));
return size;
}
Containers::Array<Int> SceneData::parentsAsArray() const {
@ -747,7 +796,7 @@ Containers::Array<Int> SceneData::parentsAsArray() const {
strings in the binary */
"Trade::SceneData::parentsInto(): field not found", {});
Containers::Array<Int> out{NoInit, std::size_t(_fields[fieldId]._size)};
parentsIntoInternal(fieldId, out);
parentsIntoInternal(fieldId, 0, out);
return out;
}
@ -813,13 +862,16 @@ std::size_t SceneData::findTransformFields(UnsignedInt& transformationFieldId, U
~std::size_t{} : _fields[fieldToCheckForSize]._size;
}
void SceneData::transformations2DIntoInternal(const UnsignedInt transformationFieldId, const UnsignedInt translationFieldId, const UnsignedInt rotationFieldId, const UnsignedInt scalingFieldId, const Containers::StridedArrayView1D<Matrix3>& destination) const {
void SceneData::transformations2DIntoInternal(const UnsignedInt transformationFieldId, const UnsignedInt translationFieldId, const UnsignedInt rotationFieldId, const UnsignedInt scalingFieldId, std::size_t offset, const Containers::StridedArrayView1D<Matrix3>& destination) const {
/* *FieldId, offset and destination.size() is assumed to be in bounds (or
an invalid field ID), checked by the callers */
/** @todo apply scalings as well if dual complex? */
/* Prefer the transformation field, if present */
if(transformationFieldId != ~UnsignedInt{}) {
const SceneFieldData& field = _fields[transformationFieldId];
const Containers::StridedArrayView1D<const void> fieldData = fieldDataFieldViewInternal(field);
const Containers::StridedArrayView1D<const void> fieldData = fieldDataFieldViewInternal(field, offset, destination.size());
const auto destination1f = Containers::arrayCast<2, Float>(destination);
if(field._fieldType == SceneFieldType::Matrix3x3) {
@ -846,7 +898,7 @@ void SceneData::transformations2DIntoInternal(const UnsignedInt transformationFi
/* Apply scaling first, if present */
if(scalingFieldId != ~UnsignedInt{}) {
const SceneFieldData& field = _fields[scalingFieldId];
const Containers::StridedArrayView1D<const void> fieldData = fieldDataFieldViewInternal(field);
const Containers::StridedArrayView1D<const void> fieldData = fieldDataFieldViewInternal(field, offset, destination.size());
if(field._fieldType == SceneFieldType::Vector2) {
applyScaling<Vector2>(fieldData, destination);
@ -861,7 +913,7 @@ void SceneData::transformations2DIntoInternal(const UnsignedInt transformationFi
/* Apply rotation second, if present */
if(rotationFieldId != ~UnsignedInt{}) {
const SceneFieldData& field = _fields[rotationFieldId];
const Containers::StridedArrayView1D<const void> fieldData = fieldDataFieldViewInternal(field);
const Containers::StridedArrayView1D<const void> fieldData = fieldDataFieldViewInternal(field, offset, destination.size());
if(field._fieldType == SceneFieldType::Complex) {
applyRotation<Complex>(fieldData, destination);
@ -876,7 +928,7 @@ void SceneData::transformations2DIntoInternal(const UnsignedInt transformationFi
/* Apply translation last, if present */
if(translationFieldId != ~UnsignedInt{}) {
const SceneFieldData& field = _fields[translationFieldId];
const Containers::StridedArrayView1D<const void> fieldData = fieldDataFieldViewInternal(field);
const Containers::StridedArrayView1D<const void> fieldData = fieldDataFieldViewInternal(field, offset, destination.size());
if(field._fieldType == SceneFieldType::Vector2) {
applyTranslation<Vector2>(fieldData, destination);
@ -902,7 +954,22 @@ void SceneData::transformations2DInto(const Containers::StridedArrayView1D<Matri
"Trade::SceneData::transformations2DInto(): no transformation-related field found", );
CORRADE_ASSERT(expectedSize == destination.size(),
"Trade::SceneData::transformations2DInto(): expected a view with" << expectedSize << "elements but got" << destination.size(), );
transformations2DIntoInternal(transformationFieldId, translationFieldId, rotationFieldId, scalingFieldId, destination);
transformations2DIntoInternal(transformationFieldId, translationFieldId, rotationFieldId, scalingFieldId, 0, destination);
}
std::size_t SceneData::transformations2DInto(const std::size_t offset, const Containers::StridedArrayView1D<Matrix3>& destination) const {
UnsignedInt transformationFieldId, translationFieldId, rotationFieldId, scalingFieldId;
#ifndef CORRADE_NO_ASSERT
const std::size_t expectedSize =
#endif
findTransformFields(transformationFieldId, translationFieldId, rotationFieldId, scalingFieldId);
CORRADE_ASSERT(expectedSize != ~std::size_t{},
"Trade::SceneData::transformations2DInto(): no transformation-related field found", {});
CORRADE_ASSERT(offset <= expectedSize,
"Trade::SceneData::transformations2DInto(): offset" << offset << "out of bounds for a field of size" << expectedSize, {});
const std::size_t size = Math::min(destination.size(), expectedSize - offset);
transformations2DIntoInternal(transformationFieldId, translationFieldId, rotationFieldId, scalingFieldId, offset, destination.prefix(size));
return size;
}
Containers::Array<Matrix3> SceneData::transformations2DAsArray() const {
@ -913,17 +980,20 @@ Containers::Array<Matrix3> SceneData::transformations2DAsArray() const {
strings in the binary */
"Trade::SceneData::transformations2DInto(): no transformation-related field found", {});
Containers::Array<Matrix3> out{NoInit, expectedSize};
transformations2DIntoInternal(transformationFieldId, translationFieldId, rotationFieldId, scalingFieldId, out);
transformations2DIntoInternal(transformationFieldId, translationFieldId, rotationFieldId, scalingFieldId, 0, out);
return out;
}
void SceneData::transformations3DIntoInternal(const UnsignedInt transformationFieldId, const UnsignedInt translationFieldId, const UnsignedInt rotationFieldId, const UnsignedInt scalingFieldId, const Containers::StridedArrayView1D<Matrix4>& destination) const {
void SceneData::transformations3DIntoInternal(const UnsignedInt transformationFieldId, const UnsignedInt translationFieldId, const UnsignedInt rotationFieldId, const UnsignedInt scalingFieldId, const std::size_t offset, const Containers::StridedArrayView1D<Matrix4>& destination) const {
/* *FieldId, offset and destination.size() is assumed to be in bounds (or
an invalid field ID), checked by the callers */
/** @todo apply scalings as well if dual quat? */
/* Prefer the transformation field, if present */
if(transformationFieldId != ~UnsignedInt{}) {
const SceneFieldData& field = _fields[transformationFieldId];
const Containers::StridedArrayView1D<const void> fieldData = fieldDataFieldViewInternal(field);
const Containers::StridedArrayView1D<const void> fieldData = fieldDataFieldViewInternal(field, offset, destination.size());
const auto destination1f = Containers::arrayCast<2, Float>(destination);
if(field._fieldType == SceneFieldType::Matrix4x4) {
@ -950,7 +1020,7 @@ void SceneData::transformations3DIntoInternal(const UnsignedInt transformationFi
/* Apply scaling first, if present */
if(scalingFieldId != ~UnsignedInt{}) {
const SceneFieldData& field = _fields[scalingFieldId];
const Containers::StridedArrayView1D<const void> fieldData = fieldDataFieldViewInternal(field);
const Containers::StridedArrayView1D<const void> fieldData = fieldDataFieldViewInternal(field, offset, destination.size());
if(field._fieldType == SceneFieldType::Vector3) {
applyScaling<Vector3>(fieldData, destination);
@ -965,7 +1035,7 @@ void SceneData::transformations3DIntoInternal(const UnsignedInt transformationFi
/* Apply rotation second, if present */
if(rotationFieldId != ~UnsignedInt{}) {
const SceneFieldData& field = _fields[rotationFieldId];
const Containers::StridedArrayView1D<const void> fieldData = fieldDataFieldViewInternal(field);
const Containers::StridedArrayView1D<const void> fieldData = fieldDataFieldViewInternal(field, offset, destination.size());
if(field._fieldType == SceneFieldType::Quaternion) {
applyRotation<Quaternion>(fieldData, destination);
@ -980,7 +1050,7 @@ void SceneData::transformations3DIntoInternal(const UnsignedInt transformationFi
/* Apply translation last, if present */
if(translationFieldId != ~UnsignedInt{}) {
const SceneFieldData& field = _fields[translationFieldId];
const Containers::StridedArrayView1D<const void> fieldData = fieldDataFieldViewInternal(field);
const Containers::StridedArrayView1D<const void> fieldData = fieldDataFieldViewInternal(field, offset, destination.size());
if(field._fieldType == SceneFieldType::Vector3) {
applyTranslation<Vector3>(fieldData, destination);
@ -1006,7 +1076,22 @@ void SceneData::transformations3DInto(const Containers::StridedArrayView1D<Matri
"Trade::SceneData::transformations3DInto(): no transformation-related field found", );
CORRADE_ASSERT(expectedSize == destination.size(),
"Trade::SceneData::transformations3DInto(): expected a view with" << expectedSize << "elements but got" << destination.size(), );
transformations3DIntoInternal(transformationFieldId, translationFieldId, rotationFieldId, scalingFieldId, destination);
transformations3DIntoInternal(transformationFieldId, translationFieldId, rotationFieldId, scalingFieldId, 0, destination);
}
std::size_t SceneData::transformations3DInto(const std::size_t offset, const Containers::StridedArrayView1D<Matrix4>& destination) const {
UnsignedInt transformationFieldId, translationFieldId, rotationFieldId, scalingFieldId;
#ifndef CORRADE_NO_ASSERT
const std::size_t expectedSize =
#endif
findTransformFields(transformationFieldId, translationFieldId, rotationFieldId, scalingFieldId);
CORRADE_ASSERT(expectedSize != ~std::size_t{},
"Trade::SceneData::transformations3DInto(): no transformation-related field found", {});
CORRADE_ASSERT(offset <= expectedSize,
"Trade::SceneData::transformations3DInto(): offset" << offset << "out of bounds for a field of size" << expectedSize, {});
const std::size_t size = Math::min(destination.size(), expectedSize - offset);
transformations3DIntoInternal(transformationFieldId, translationFieldId, rotationFieldId, scalingFieldId, offset, destination.prefix(size));
return size;
}
Containers::Array<Matrix4> SceneData::transformations3DAsArray() const {
@ -1017,22 +1102,16 @@ Containers::Array<Matrix4> SceneData::transformations3DAsArray() const {
strings in the binary */
"Trade::SceneData::transformations3DInto(): no transformation-related field found", {});
Containers::Array<Matrix4> out{NoInit, expectedSize};
transformations3DIntoInternal(transformationFieldId, translationFieldId, rotationFieldId, scalingFieldId, out);
transformations3DIntoInternal(transformationFieldId, translationFieldId, rotationFieldId, scalingFieldId, 0, out);
return out;
}
void SceneData::indexFieldIntoInternal(
#ifndef CORRADE_NO_ASSERT
const char* const prefix,
#endif
const UnsignedInt fieldId, const Containers::StridedArrayView1D<UnsignedInt>& destination) const
{
CORRADE_ASSERT(fieldId != ~UnsignedInt{},
prefix << "field not found", );
void SceneData::indexFieldIntoInternal(const UnsignedInt fieldId, const std::size_t offset, const Containers::StridedArrayView1D<UnsignedInt>& destination) const {
/* fieldId, offset and destination.size() is assumed to be in bounds,
checked by the callers */
const SceneFieldData& field = _fields[fieldId];
CORRADE_ASSERT(destination.size() == field._size,
prefix << "expected a view with" << field._size << "elements but got" << destination.size(), );
const Containers::StridedArrayView1D<const void> fieldData = fieldDataFieldViewInternal(field);
const Containers::StridedArrayView1D<const void> fieldData = fieldDataFieldViewInternal(field, offset, destination.size());
const auto destination1ui = Containers::arrayCast<2, UnsignedInt>(destination);
if(field._fieldType == SceneFieldType::UnsignedInt)
@ -1044,111 +1123,155 @@ void SceneData::indexFieldIntoInternal(
else CORRADE_INTERNAL_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */
}
Containers::Array<UnsignedInt> SceneData::indexFieldAsArrayInternal(
#ifndef CORRADE_NO_ASSERT
const char* const prefix,
#endif
const SceneField name) const
{
const UnsignedInt fieldId = fieldFor(name);
CORRADE_ASSERT(fieldId != ~UnsignedInt{}, prefix << "field not found", {});
Containers::Array<UnsignedInt> SceneData::indexFieldAsArrayInternal(const UnsignedInt fieldId) const {
Containers::Array<UnsignedInt> out{NoInit, std::size_t(_fields[fieldId]._size)};
indexFieldIntoInternal(
#ifndef CORRADE_NO_ASSERT
prefix,
#endif
fieldId, out);
indexFieldIntoInternal(fieldId, 0, out);
return out;
}
void SceneData::meshesInto(const Containers::StridedArrayView1D<UnsignedInt>& destination) const {
indexFieldIntoInternal(
#ifndef CORRADE_NO_ASSERT
"Trade::SceneData::meshesInto():",
#endif
fieldFor(SceneField::Mesh), destination);
const UnsignedInt fieldId = fieldFor(SceneField::Mesh);
CORRADE_ASSERT(fieldId != ~UnsignedInt{},
"Trade::SceneData::meshesInto(): field not found", );
CORRADE_ASSERT(destination.size() == _fields[fieldId]._size,
"Trade::SceneData::meshesInto(): expected a view with" << _fields[fieldId]._size << "elements but got" << destination.size(), );
indexFieldIntoInternal(fieldId, 0, destination);
}
std::size_t SceneData::meshesInto(const std::size_t offset, const Containers::StridedArrayView1D<UnsignedInt>& destination) const {
const UnsignedInt fieldId = fieldFor(SceneField::Mesh);
CORRADE_ASSERT(fieldId != ~UnsignedInt{},
"Trade::SceneData::meshesInto(): field not found", {});
CORRADE_ASSERT(offset <= _fields[fieldId]._size,
"Trade::SceneData::meshesInto(): offset" << offset << "out of bounds for a field of size" << _fields[fieldId]._size, {});
const std::size_t size = Math::min(destination.size(), std::size_t(_fields[fieldId]._size) - offset);
indexFieldIntoInternal(fieldId, offset, destination.prefix(size));
return size;
}
Containers::Array<UnsignedInt> SceneData::meshesAsArray() const {
return indexFieldAsArrayInternal(
#ifndef CORRADE_NO_ASSERT
const UnsignedInt fieldId = fieldFor(SceneField::Mesh);
CORRADE_ASSERT(fieldId != ~UnsignedInt{},
/* Using the same message as in Into() to avoid too many redundant
strings in the binary */
"Trade::SceneData::meshesInto():",
#endif
SceneField::Mesh);
"Trade::SceneData::meshesInto(): field not found", {});
return indexFieldAsArrayInternal(fieldId);
}
void SceneData::meshMaterialsInto(const Containers::StridedArrayView1D<UnsignedInt>& destination) const {
indexFieldIntoInternal(
#ifndef CORRADE_NO_ASSERT
"Trade::SceneData::meshMaterialsInto():",
#endif
fieldFor(SceneField::MeshMaterial), destination);
const UnsignedInt fieldId = fieldFor(SceneField::MeshMaterial);
CORRADE_ASSERT(fieldId != ~UnsignedInt{},
"Trade::SceneData::meshMaterialsInto(): field not found", );
CORRADE_ASSERT(destination.size() == _fields[fieldId]._size,
"Trade::SceneData::meshMaterialsInto(): expected a view with" << _fields[fieldId]._size << "elements but got" << destination.size(), );
indexFieldIntoInternal(fieldId, 0, destination);
}
std::size_t SceneData::meshMaterialsInto(const std::size_t offset, const Containers::StridedArrayView1D<UnsignedInt>& destination) const {
const UnsignedInt fieldId = fieldFor(SceneField::MeshMaterial);
CORRADE_ASSERT(fieldId != ~UnsignedInt{},
"Trade::SceneData::meshMaterialsInto(): field not found", {});
CORRADE_ASSERT(offset <= _fields[fieldId]._size,
"Trade::SceneData::meshMaterialsInto(): offset" << offset << "out of bounds for a field of size" << _fields[fieldId]._size, {});
const std::size_t size = Math::min(destination.size(), std::size_t(_fields[fieldId]._size) - offset);
indexFieldIntoInternal(fieldId, offset, destination.prefix(size));
return size;
}
Containers::Array<UnsignedInt> SceneData::meshMaterialsAsArray() const {
return indexFieldAsArrayInternal(
#ifndef CORRADE_NO_ASSERT
const UnsignedInt fieldId = fieldFor(SceneField::MeshMaterial);
CORRADE_ASSERT(fieldId != ~UnsignedInt{},
/* Using the same message as in Into() to avoid too many redundant
strings in the binary */
"Trade::SceneData::meshMaterialsInto():",
#endif
SceneField::MeshMaterial);
"Trade::SceneData::meshMaterialsInto(): field not found", {});
return indexFieldAsArrayInternal(fieldId);
}
void SceneData::lightsInto(const Containers::StridedArrayView1D<UnsignedInt>& destination) const {
indexFieldIntoInternal(
#ifndef CORRADE_NO_ASSERT
"Trade::SceneData::lightsInto():",
#endif
fieldFor(SceneField::Light), destination);
const UnsignedInt fieldId = fieldFor(SceneField::Light);
CORRADE_ASSERT(fieldId != ~UnsignedInt{},
"Trade::SceneData::lightsInto(): field not found", );
CORRADE_ASSERT(destination.size() == _fields[fieldId]._size,
"Trade::SceneData::lightsInto(): expected a view with" << _fields[fieldId]._size << "elements but got" << destination.size(), );
indexFieldIntoInternal(fieldId, 0, destination);
}
std::size_t SceneData::lightsInto(const std::size_t offset, const Containers::StridedArrayView1D<UnsignedInt>& destination) const {
const UnsignedInt fieldId = fieldFor(SceneField::Light);
CORRADE_ASSERT(fieldId != ~UnsignedInt{},
"Trade::SceneData::lightsInto(): field not found", {});
CORRADE_ASSERT(offset <= _fields[fieldId]._size,
"Trade::SceneData::lightsInto(): offset" << offset << "out of bounds for a field of size" << _fields[fieldId]._size, {});
const std::size_t size = Math::min(destination.size(), std::size_t(_fields[fieldId]._size) - offset);
indexFieldIntoInternal(fieldId, offset, destination.prefix(size));
return size;
}
Containers::Array<UnsignedInt> SceneData::lightsAsArray() const {
return indexFieldAsArrayInternal(
#ifndef CORRADE_NO_ASSERT
const UnsignedInt fieldId = fieldFor(SceneField::Light);
CORRADE_ASSERT(fieldId != ~UnsignedInt{},
/* Using the same message as in Into() to avoid too many redundant
strings in the binary */
"Trade::SceneData::lightsInto():",
#endif
SceneField::Light);
"Trade::SceneData::lightsInto(): field not found", {});
return indexFieldAsArrayInternal(fieldId);
}
void SceneData::camerasInto(const Containers::StridedArrayView1D<UnsignedInt>& destination) const {
indexFieldIntoInternal(
#ifndef CORRADE_NO_ASSERT
"Trade::SceneData::camerasInto():",
#endif
fieldFor(SceneField::Camera), destination);
const UnsignedInt fieldId = fieldFor(SceneField::Camera);
CORRADE_ASSERT(fieldId != ~UnsignedInt{},
"Trade::SceneData::camerasInto(): field not found", );
CORRADE_ASSERT(destination.size() == _fields[fieldId]._size,
"Trade::SceneData::camerasInto(): expected a view with" << _fields[fieldId]._size << "elements but got" << destination.size(), );
indexFieldIntoInternal(fieldId, 0, destination);
}
std::size_t SceneData::camerasInto(const std::size_t offset, const Containers::StridedArrayView1D<UnsignedInt>& destination) const {
const UnsignedInt fieldId = fieldFor(SceneField::Camera);
CORRADE_ASSERT(fieldId != ~UnsignedInt{},
"Trade::SceneData::camerasInto(): field not found", {});
CORRADE_ASSERT(offset <= _fields[fieldId]._size,
"Trade::SceneData::camerasInto(): offset" << offset << "out of bounds for a field of size" << _fields[fieldId]._size, {});
const std::size_t size = Math::min(destination.size(), std::size_t(_fields[fieldId]._size) - offset);
indexFieldIntoInternal(fieldId, offset, destination.prefix(size));
return size;
}
Containers::Array<UnsignedInt> SceneData::camerasAsArray() const {
return indexFieldAsArrayInternal(
#ifndef CORRADE_NO_ASSERT
const UnsignedInt fieldId = fieldFor(SceneField::Camera);
CORRADE_ASSERT(fieldId != ~UnsignedInt{},
/* Using the same message as in Into() to avoid too many redundant
strings in the binary */
"Trade::SceneData::camerasInto():",
#endif
SceneField::Camera);
"Trade::SceneData::camerasInto(): field not found", {});
return indexFieldAsArrayInternal(fieldId);
}
void SceneData::skinsInto(const Containers::StridedArrayView1D<UnsignedInt>& destination) const {
indexFieldIntoInternal(
#ifndef CORRADE_NO_ASSERT
"Trade::SceneData::skinsInto():",
#endif
fieldFor(SceneField::Skin), destination);
const UnsignedInt fieldId = fieldFor(SceneField::Skin);
CORRADE_ASSERT(fieldId != ~UnsignedInt{},
"Trade::SceneData::skinsInto(): field not found", );
CORRADE_ASSERT(destination.size() == _fields[fieldId]._size,
"Trade::SceneData::skinsInto(): expected a view with" << _fields[fieldId]._size << "elements but got" << destination.size(), );
indexFieldIntoInternal(fieldId, 0, destination);
}
std::size_t SceneData::skinsInto(const std::size_t offset, const Containers::StridedArrayView1D<UnsignedInt>& destination) const {
const UnsignedInt fieldId = fieldFor(SceneField::Skin);
CORRADE_ASSERT(fieldId != ~UnsignedInt{},
"Trade::SceneData::skinsInto(): field not found", {});
CORRADE_ASSERT(offset <= _fields[fieldId]._size,
"Trade::SceneData::skinsInto(): offset" << offset << "out of bounds for a field of size" << _fields[fieldId]._size, {});
const std::size_t size = Math::min(destination.size(), std::size_t(_fields[fieldId]._size) - offset);
indexFieldIntoInternal(fieldId, offset, destination.prefix(size));
return size;
}
Containers::Array<UnsignedInt> SceneData::skinsAsArray() const {
return indexFieldAsArrayInternal(
#ifndef CORRADE_NO_ASSERT
const UnsignedInt fieldId = fieldFor(SceneField::Skin);
CORRADE_ASSERT(fieldId != ~UnsignedInt{},
/* Using the same message as in Into() to avoid too many redundant
strings in the binary */
"Trade::SceneData::skinsInto():",
#endif
SceneField::Skin);
"Trade::SceneData::skinsInto(): field not found", {});
return indexFieldAsArrayInternal(fieldId);
}
Containers::Array<SceneFieldData> SceneData::releaseFieldData() {

155
src/Magnum/Trade/SceneData.h

@ -1264,6 +1264,19 @@ class MAGNUM_TRADE_EXPORT SceneData {
*/
void objectsInto(UnsignedInt fieldId, const Containers::StridedArrayView1D<UnsignedInt>& destination) const;
/**
* @brief A subrange of object mapping for given field as 32-bit integers into a pre-allocated view
* @m_since_latest
*
* Compared to @ref objectsInto(UnsignedInt, const Containers::StridedArrayView1D<UnsignedInt>&) const
* extracts only a subrange of the object mapping defined by @p offset
* and size of the @p destination view, returning the count of items
* actually extracted. The @p offset is expected to not be larger than
* the field size.
* @see @ref fieldSize(UnsignedInt) const
*/
std::size_t objectsInto(UnsignedInt fieldId, std::size_t offset, const Containers::StridedArrayView1D<UnsignedInt>& destination) const;
/**
* @brief Object mapping for given named field as 32-bit integers
* @m_since_latest
@ -1293,6 +1306,19 @@ class MAGNUM_TRADE_EXPORT SceneData {
*/
void objectsInto(SceneField fieldName, const Containers::StridedArrayView1D<UnsignedInt>& destination) const;
/**
* @brief A subrange of object mapping for given named field as 32-bit integers into a pre-allocated view
* @m_since_latest
*
* Compared to @ref objectsInto(SceneField, const Containers::StridedArrayView1D<UnsignedInt>&) const
* extracts only a subrange of the object mapping defined by @p offset
* and size of the @p destination view, returning the count of items
* actually extracted. The @p offset is expected to not be larger than
* the field size.
* @see @ref fieldSize(SceneField) const
*/
std::size_t objectsInto(SceneField fieldName, std::size_t offset, const Containers::StridedArrayView1D<UnsignedInt>& destination) const;
/**
* @brief Parent indices as 32-bit integers
* @m_since_latest
@ -1321,6 +1347,19 @@ class MAGNUM_TRADE_EXPORT SceneData {
*/
void parentsInto(const Containers::StridedArrayView1D<Int>& destination) const;
/**
* @brief A subrange of parent indices as 32-bit integers into a pre-allocated view
* @m_since_latest
*
* Compared to @ref parentsInto(const Containers::StridedArrayView1D<Int>&) const
* extracts only a subrange of the field defined by @p offset and size
* of the @p destination view, returning the count of items actually
* extracted. The @p offset is expected to not be larger than the field
* size.
* @see @ref fieldSize(SceneField) const
*/
std::size_t parentsInto(std::size_t offset, const Containers::StridedArrayView1D<Int>& destination) const;
/**
* @brief 2D transformations as 3x3 float matrices
* @m_since_latest
@ -1351,6 +1390,19 @@ class MAGNUM_TRADE_EXPORT SceneData {
*/
void transformations2DInto(const Containers::StridedArrayView1D<Matrix3>& destination) const;
/**
* @brief A subrange of 2D transformations as 3x3 float matrices into a pre-allocated view
* @m_since_latest
*
* Compared to @ref transformations2DInto(const Containers::StridedArrayView1D<Matrix3>&) const
* extracts only a subrange of the field defined by @p offset and size
* of the @p destination view, returning the count of items actually
* extracted. The @p offset is expected to not be larger than the field
* size.
* @see @ref fieldSize(SceneField) const
*/
std::size_t transformations2DInto(std::size_t offset, const Containers::StridedArrayView1D<Matrix3>& destination) const;
/**
* @brief 3D transformations as 4x4 float matrices
* @m_since_latest
@ -1381,6 +1433,19 @@ class MAGNUM_TRADE_EXPORT SceneData {
*/
void transformations3DInto(const Containers::StridedArrayView1D<Matrix4>& destination) const;
/**
* @brief A subrange of 3D transformations as 4x4 float matrices into a pre-allocated view
* @m_since_latest
*
* Compared to @ref transformations3DInto(const Containers::StridedArrayView1D<Matrix4>&) const
* extracts only a subrange of the field defined by @p offset and size
* of the @p destination view, returning the count of items actually
* extracted. The @p offset is expected to not be larger than the field
* size.
* @see @ref fieldSize(SceneField) const
*/
std::size_t transformations3DInto(std::size_t offset, const Containers::StridedArrayView1D<Matrix4>& destination) const;
/**
* @brief Mesh IDs as 32-bit integers
* @m_since_latest
@ -1404,6 +1469,19 @@ class MAGNUM_TRADE_EXPORT SceneData {
*/
void meshesInto(const Containers::StridedArrayView1D<UnsignedInt>& destination) const;
/**
* @brief A subrange of mesh IDs as 32-bit integers into a pre-allocated view
* @m_since_latest
*
* Compared to @ref meshesInto(const Containers::StridedArrayView1D<UnsignedInt>&) const
* extracts only a subrange of the field defined by @p offset and size
* of the @p destination view, returning the count of items actually
* extracted. The @p offset is expected to not be larger than the field
* size.
* @see @ref fieldSize(SceneField) const
*/
std::size_t meshesInto(std::size_t offset, const Containers::StridedArrayView1D<UnsignedInt>& destination) const;
/**
* @brief Mesh material IDs as 32-bit integers
* @m_since_latest
@ -1427,6 +1505,19 @@ class MAGNUM_TRADE_EXPORT SceneData {
*/
void meshMaterialsInto(const Containers::StridedArrayView1D<UnsignedInt>& destination) const;
/**
* @brief A subrange of mesh material IDs as 32-bit integers into a pre-allocated view
* @m_since_latest
*
* Compared to @ref meshMaterialsInto(const Containers::StridedArrayView1D<UnsignedInt>&) const
* extracts only a subrange of the field defined by @p offset and size
* of the @p destination view, returning the count of items actually
* extracted. The @p offset is expected to not be larger than the field
* size.
* @see @ref fieldSize(SceneField) const
*/
std::size_t meshMaterialsInto(std::size_t offset, const Containers::StridedArrayView1D<UnsignedInt>& destination) const;
/**
* @brief Light IDs as 32-bit integers
* @m_since_latest
@ -1450,6 +1541,19 @@ class MAGNUM_TRADE_EXPORT SceneData {
*/
void lightsInto(const Containers::StridedArrayView1D<UnsignedInt>& destination) const;
/**
* @brief A subrange of light IDs as 32-bit integers into a pre-allocated view
* @m_since_latest
*
* Compared to @ref lightsInto(const Containers::StridedArrayView1D<UnsignedInt>&) const
* extracts only a subrange of the field defined by @p offset and size
* of the @p destination view, returning the count of items actually
* extracted. The @p offset is expected to not be larger than the field
* size.
* @see @ref fieldSize(SceneField) const
*/
std::size_t lightsInto(std::size_t offset, const Containers::StridedArrayView1D<UnsignedInt>& destination) const;
/**
* @brief Camera IDs as 32-bit integers
* @m_since_latest
@ -1473,6 +1577,19 @@ class MAGNUM_TRADE_EXPORT SceneData {
*/
void camerasInto(const Containers::StridedArrayView1D<UnsignedInt>& destination) const;
/**
* @brief A subrange of camera IDs as 32-bit integers into a pre-allocated view
* @m_since_latest
*
* Compared to @ref camerasInto(const Containers::StridedArrayView1D<UnsignedInt>&) const
* extracts only a subrange of the field defined by @p offset and size
* of the @p destination view, returning the count of items actually
* extracted. The @p offset is expected to not be larger than the field
* size.
* @see @ref fieldSize(SceneField) const
*/
std::size_t camerasInto(std::size_t offset, const Containers::StridedArrayView1D<UnsignedInt>& destination) const;
/**
* @brief Skin IDs as 32-bit integers
* @m_since_latest
@ -1496,6 +1613,19 @@ class MAGNUM_TRADE_EXPORT SceneData {
*/
void skinsInto(const Containers::StridedArrayView1D<UnsignedInt>& destination) const;
/**
* @brief A subrange of skin IDs as 32-bit integers into a pre-allocated view
* @m_since_latest
*
* Compared to @ref skinsInto(const Containers::StridedArrayView1D<UnsignedInt>&) const
* extracts only a subrange of the field defined by @p offset and size
* of the @p destination view, returning the count of items actually
* extracted. The @p offset is expected to not be larger than the field
* size.
* @see @ref fieldSize(SceneField) const
*/
std::size_t skinsInto(std::size_t offset, const Containers::StridedArrayView1D<UnsignedInt>& destination) const;
/**
* @brief Release field data storage
* @m_since_latest
@ -1542,28 +1672,25 @@ class MAGNUM_TRADE_EXPORT SceneData {
/* Internal helper that doesn't assert, unlike fieldId() */
UnsignedInt fieldFor(SceneField name) const;
/* Like objects() / field(), but returning just a 1D view */
/* Like objects() / field(), but returning just a 1D view, sliced from
offset to offset + size. The parameterless overloads are equal to
offset = 0 and size = field.size(). */
MAGNUM_TRADE_LOCAL Containers::StridedArrayView1D<const void> fieldDataObjectViewInternal(const SceneFieldData& field, std::size_t offset, std::size_t size) const;
MAGNUM_TRADE_LOCAL Containers::StridedArrayView1D<const void> fieldDataObjectViewInternal(const SceneFieldData& field) const;
MAGNUM_TRADE_LOCAL Containers::StridedArrayView1D<const void> fieldDataFieldViewInternal(const SceneFieldData& field, std::size_t offset, std::size_t size) const;
MAGNUM_TRADE_LOCAL Containers::StridedArrayView1D<const void> fieldDataFieldViewInternal(const SceneFieldData& field) const;
#ifndef CORRADE_NO_ASSERT
template<class T> bool checkFieldTypeCompatibility(const SceneFieldData& attribute, const char* prefix) const;
#endif
MAGNUM_TRADE_LOCAL void parentsIntoInternal(UnsignedInt fieldId, const Containers::StridedArrayView1D<Int>& destination) const;
MAGNUM_TRADE_LOCAL void objectsIntoInternal(UnsignedInt fieldId, std::size_t offset, const Containers::StridedArrayView1D<UnsignedInt>& destination) const;
MAGNUM_TRADE_LOCAL void parentsIntoInternal(UnsignedInt fieldId, std::size_t offset, const Containers::StridedArrayView1D<Int>& destination) const;
MAGNUM_TRADE_LOCAL std::size_t findTransformFields(UnsignedInt& transformationFieldId, UnsignedInt& translationFieldId, UnsignedInt& rotationFieldId, UnsignedInt& scalingFieldId) const;
MAGNUM_TRADE_LOCAL void transformations2DIntoInternal(UnsignedInt transformationFieldId, UnsignedInt translationFieldId, UnsignedInt rotationFieldId, UnsignedInt scalingFieldId, const Containers::StridedArrayView1D<Matrix3>& destination) const;
MAGNUM_TRADE_LOCAL void transformations3DIntoInternal(UnsignedInt transformationFieldId, UnsignedInt translationFieldId, UnsignedInt rotationFieldId, UnsignedInt scalingFieldId, const Containers::StridedArrayView1D<Matrix4>& destination) const;
MAGNUM_TRADE_LOCAL void indexFieldIntoInternal(
#ifndef CORRADE_NO_ASSERT
const char* const prefix,
#endif
const UnsignedInt fieldId, const Containers::StridedArrayView1D<UnsignedInt>& destination) const;
MAGNUM_TRADE_LOCAL Containers::Array<UnsignedInt> indexFieldAsArrayInternal(
#ifndef CORRADE_NO_ASSERT
const char* const prefix,
#endif
const SceneField name) const;
MAGNUM_TRADE_LOCAL void transformations2DIntoInternal(UnsignedInt transformationFieldId, UnsignedInt translationFieldId, UnsignedInt rotationFieldId, UnsignedInt scalingFieldId, std::size_t offset, const Containers::StridedArrayView1D<Matrix3>& destination) const;
MAGNUM_TRADE_LOCAL void transformations3DIntoInternal(UnsignedInt transformationFieldId, UnsignedInt translationFieldId, UnsignedInt rotationFieldId, UnsignedInt scalingFieldId, std::size_t offset, const Containers::StridedArrayView1D<Matrix4>& destination) const;
MAGNUM_TRADE_LOCAL void indexFieldIntoInternal(const UnsignedInt fieldId, std::size_t offset, const Containers::StridedArrayView1D<UnsignedInt>& destination) const;
MAGNUM_TRADE_LOCAL Containers::Array<UnsignedInt> indexFieldAsArrayInternal(const UnsignedInt fieldId) const;
DataFlags _dataFlags;
SceneObjectType _objectType;

904
src/Magnum/Trade/Test/SceneDataTest.cpp

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save