mirror of https://github.com/mosra/magnum.git
30 changed files with 1599 additions and 1 deletions
@ -0,0 +1,53 @@
|
||||
# |
||||
# This file is part of Magnum. |
||||
# |
||||
# Copyright © 2010, 2011, 2012, 2013, 2014 |
||||
# Vladimír Vondruš <mosra@centrum.cz> |
||||
# |
||||
# Permission is hereby granted, free of charge, to any person obtaining a |
||||
# copy of this software and associated documentation files (the "Software"), |
||||
# to deal in the Software without restriction, including without limitation |
||||
# the rights to use, copy, modify, merge, publish, distribute, sublicense, |
||||
# and/or sell copies of the Software, and to permit persons to whom the |
||||
# Software is furnished to do so, subject to the following conditions: |
||||
# |
||||
# The above copyright notice and this permission notice shall be included |
||||
# in all copies or substantial portions of the Software. |
||||
# |
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
||||
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
||||
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
||||
# DEALINGS IN THE SOFTWARE. |
||||
# |
||||
|
||||
add_library(ObjImporterObjects OBJECT ObjImporter.cpp) |
||||
if(NOT BUILD_STATIC OR BUILD_STATIC_PIC) |
||||
set_target_properties(ObjImporterObjects PROPERTIES COMPILE_FLAGS "${CMAKE_SHARED_LIBRARY_CXX_FLAGS}") |
||||
endif() |
||||
|
||||
add_plugin(ObjImporter ${MAGNUM_PLUGINS_IMPORTER_INSTALL_DIR} |
||||
ObjImporter.conf |
||||
$<TARGET_OBJECTS:ObjImporterObjects> |
||||
pluginRegistration.cpp) |
||||
target_link_libraries(ObjImporter Magnum MagnumMeshTools) |
||||
|
||||
install(FILES ObjImporter.h DESTINATION ${MAGNUM_PLUGINS_INCLUDE_INSTALL_DIR}/ObjImporter) |
||||
|
||||
if(BUILD_TESTS) |
||||
add_library(ObjImporterTestLib STATIC $<TARGET_OBJECTS:ObjImporterObjects>) |
||||
target_link_libraries(ObjImporterTestLib Magnum MagnumMeshTools) |
||||
|
||||
# On Windows we need to install first and then run the tests to avoid "DLL |
||||
# not found" hell, thus we need to install this too |
||||
if(WIN32 AND NOT CMAKE_CROSSCOMPILING) |
||||
install(TARGETS ObjImporterTestLib |
||||
RUNTIME DESTINATION ${MAGNUM_BINARY_INSTALL_DIR} |
||||
LIBRARY DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR} |
||||
ARCHIVE DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR}) |
||||
endif() |
||||
|
||||
add_subdirectory(Test) |
||||
endif() |
||||
@ -0,0 +1,408 @@
|
||||
/*
|
||||
This file is part of Magnum. |
||||
|
||||
Copyright © 2010, 2011, 2012, 2013, 2014 |
||||
Vladimír Vondruš <mosra@centrum.cz> |
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a |
||||
copy of this software and associated documentation files (the "Software"), |
||||
to deal in the Software without restriction, including without limitation |
||||
the rights to use, copy, modify, merge, publish, distribute, sublicense, |
||||
and/or sell copies of the Software, and to permit persons to whom the |
||||
Software is furnished to do so, subject to the following conditions: |
||||
|
||||
The above copyright notice and this permission notice shall be included |
||||
in all copies or substantial portions of the Software. |
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
||||
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
||||
DEALINGS IN THE SOFTWARE. |
||||
*/ |
||||
|
||||
#include "ObjImporter.h" |
||||
|
||||
#include <fstream> |
||||
#include <limits> |
||||
#include <sstream> |
||||
#include <unordered_map> |
||||
#include <Corrade/Containers/Array.h> |
||||
#include <Corrade/Utility/String.h> |
||||
|
||||
#include "Magnum/Math/Vector3.h" |
||||
#include "Magnum/Trade/MeshData3D.h" |
||||
#include <Magnum/Mesh.h> |
||||
#include <Magnum/MeshTools/CombineIndexedArrays.h> |
||||
#include <Magnum/MeshTools/Duplicate.h> |
||||
|
||||
namespace Magnum { namespace Trade { |
||||
|
||||
struct ObjImporter::File { |
||||
std::unordered_map<std::string, UnsignedInt> meshesForName; |
||||
std::vector<std::string> meshNames; |
||||
std::vector<std::pair<std::streampos, std::streampos>> meshes; |
||||
std::unique_ptr<std::istream> in; |
||||
}; |
||||
|
||||
namespace { |
||||
|
||||
void ignoreLine(std::istream& in) { |
||||
in.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); |
||||
} |
||||
|
||||
template<std::size_t size> Math::Vector<size, Float> extractFloatData(std::string str, Float* extra = nullptr) { |
||||
std::vector<std::string> data = Utility::String::splitWithoutEmptyParts(str, ' '); |
||||
if(data.size() < size || data.size() > size + (extra ? 1 : 0)) { |
||||
Error() << "Trade::ObjImporter::mesh3D(): invalid float array size"; |
||||
throw 0; |
||||
} |
||||
|
||||
Math::Vector<size, Float> output; |
||||
for(std::size_t i = 0; i != size; ++i) |
||||
output[i] = std::stof(data[i]); |
||||
|
||||
if(data.size() == size+1) *extra = std::stof(data.back()); |
||||
|
||||
return output; |
||||
} |
||||
|
||||
template<class T> void reindex(const std::vector<UnsignedInt>& indices, std::vector<T>& data) { |
||||
/* Check that indices are in range */ |
||||
for(UnsignedInt i: indices) if(i >= data.size()) { |
||||
Error() << "Trade::ObjImporter::mesh3D(): index out of range"; |
||||
throw 0; |
||||
} |
||||
|
||||
data = MeshTools::duplicate(indices, data); |
||||
} |
||||
|
||||
} |
||||
|
||||
ObjImporter::ObjImporter() = default; |
||||
|
||||
ObjImporter::ObjImporter(PluginManager::AbstractManager& manager, std::string plugin): AbstractImporter(manager, std::move(plugin)) {} |
||||
|
||||
ObjImporter::~ObjImporter() = default; |
||||
|
||||
auto ObjImporter::doFeatures() const -> Features { return Feature::OpenData; } |
||||
|
||||
void ObjImporter::doClose() { _file.reset(); } |
||||
|
||||
bool ObjImporter::doIsOpened() const { return !!_file; } |
||||
|
||||
void ObjImporter::doOpenFile(const std::string& filename) { |
||||
/* Open file in *text* mode (to avoid \r handling) */ |
||||
std::unique_ptr<std::istream> in{new std::ifstream{filename}}; |
||||
if(!in->good()) { |
||||
Error() << "Trade::ObjImporter::openFile(): cannot open file" << filename; |
||||
return; |
||||
} |
||||
|
||||
_file.reset(new File); |
||||
_file->in = std::move(in); |
||||
parseMeshNames(); |
||||
} |
||||
|
||||
void ObjImporter::doOpenData(Containers::ArrayReference<const unsigned char> data) { |
||||
/* Open file in *text* mode (to avoid \r handling) */ |
||||
_file.reset(new File); |
||||
_file->in.reset(new std::istringstream{{reinterpret_cast<const char*>(data.begin()), data.size()}}); |
||||
|
||||
parseMeshNames(); |
||||
} |
||||
|
||||
void ObjImporter::parseMeshNames() { |
||||
bool hasData = false; |
||||
std::string name; |
||||
std::streampos begin = 0; |
||||
while(_file->in->good()) { |
||||
/* The previous object ends at the beginning of this line */ |
||||
const std::streampos end = _file->in->tellg(); |
||||
|
||||
/* Comment line */ |
||||
if(_file->in->peek() == '#') { |
||||
ignoreLine(*_file->in); |
||||
continue; |
||||
} |
||||
|
||||
/* Parse the keyword */ |
||||
std::string keyword; |
||||
*_file->in >> keyword; |
||||
|
||||
/* Object name */ |
||||
if(keyword == "o") { |
||||
/* If there was any previous object, this is name of new object,
|
||||
save the previous one */ |
||||
if(hasData) { |
||||
if(!name.empty()) _file->meshesForName.emplace(name, _file->meshes.size()); |
||||
_file->meshNames.emplace_back(std::move(name)); |
||||
_file->meshes.emplace_back(begin, end); |
||||
|
||||
/* Otherwise it's the name of first object (there weren't any data
|
||||
before) */ |
||||
} else hasData = true; |
||||
|
||||
/* Get name of new object, the object then starts at the next line */ |
||||
std::getline(*_file->in, name); |
||||
name = Utility::String::trim(name); |
||||
begin = _file->in->tellg(); |
||||
continue; |
||||
} |
||||
|
||||
/* If there are any data before the first name, it means that the first
|
||||
object can be unnamed */ |
||||
if(!hasData) for(const std::string& data: {"v", "vt", "vn", "p", "l", "f"}) { |
||||
if(keyword == data) { |
||||
hasData = true; |
||||
break; |
||||
} |
||||
} |
||||
|
||||
/* Ignore the rest of the line */ |
||||
ignoreLine(*_file->in); |
||||
} |
||||
|
||||
/* Add also the last object */ |
||||
_file->in->clear(); |
||||
_file->in->seekg(0, std::ios::end); |
||||
if(!name.empty()) _file->meshesForName.emplace(name, _file->meshes.size()); |
||||
_file->meshNames.emplace_back(std::move(name)); |
||||
_file->meshes.emplace_back(begin, _file->in->tellg()); |
||||
} |
||||
|
||||
UnsignedInt ObjImporter::doMesh3DCount() const { return _file->meshes.size(); } |
||||
|
||||
Int ObjImporter::doMesh3DForName(const std::string& name) { |
||||
const auto it = _file->meshesForName.find(name); |
||||
return it == _file->meshesForName.end() ? -1 : it->second; |
||||
} |
||||
|
||||
std::string ObjImporter::doMesh3DName(UnsignedInt id) { |
||||
return _file->meshNames[id]; |
||||
} |
||||
|
||||
std::optional<MeshData3D> ObjImporter::doMesh3D(UnsignedInt id) { |
||||
/* Seek the file */ |
||||
std::streampos begin, end; |
||||
std::tie(begin, end) = _file->meshes[id]; |
||||
_file->in->seekg(begin); |
||||
|
||||
std::optional<MeshPrimitive> primitive; |
||||
std::vector<Vector3> positions; |
||||
std::vector<std::vector<Vector2>> textureCoordinates; |
||||
std::vector<std::vector<Vector3>> normals; |
||||
std::vector<UnsignedInt> positionIndices; |
||||
std::vector<UnsignedInt> textureCoordinateIndices; |
||||
std::vector<UnsignedInt> normalIndices; |
||||
|
||||
try { while(_file->in->good() && _file->in->tellg() < end) { |
||||
/* Ignore comments */ |
||||
if(_file->in->peek() == '#') { |
||||
ignoreLine(*_file->in); |
||||
continue; |
||||
} |
||||
|
||||
/* Get the line */ |
||||
std::string line; |
||||
std::getline(*_file->in, line); |
||||
line = Utility::String::trim(line); |
||||
|
||||
/* Ignore empty lines */ |
||||
if(line.empty()) continue; |
||||
|
||||
/* Split the line into keyword and contents */ |
||||
const std::size_t keywordEnd = line.find(' '); |
||||
const std::string keyword = line.substr(0, keywordEnd); |
||||
const std::string contents = keywordEnd != std::string::npos ? |
||||
Utility::String::ltrim(line.substr(keywordEnd+1)) : ""; |
||||
|
||||
/* Vertex position */ |
||||
if(keyword == "v") { |
||||
Float extra{1.0f}; |
||||
const Vector3 data = extractFloatData<3>(contents, &extra); |
||||
if(!Math::TypeTraits<Float>::equals(extra, 1.0f)) { |
||||
Error() << "Trade::ObjImporter::mesh3D(): homogeneous coordinates are not supported"; |
||||
return std::nullopt; |
||||
} |
||||
|
||||
positions.push_back(data); |
||||
|
||||
/* Texture coordinate */ |
||||
} else if(keyword == "vt") { |
||||
Float extra{0.0f}; |
||||
const auto data = extractFloatData<2>(contents, &extra); |
||||
if(!Math::TypeTraits<Float>::equals(extra, 0.0f)) { |
||||
Error() << "Trade::ObjImporter::mesh3D(): 3D texture coordinates are not supported"; |
||||
return std::nullopt; |
||||
} |
||||
|
||||
if(textureCoordinates.empty()) textureCoordinates.push_back({}); |
||||
textureCoordinates.front().push_back(data); |
||||
|
||||
/* Normal */ |
||||
} else if(keyword == "vn") { |
||||
if(normals.empty()) normals.push_back({}); |
||||
normals.front().push_back(extractFloatData<3>(contents)); |
||||
|
||||
/* Indices */ |
||||
} else if(keyword == "p" || keyword == "l" || keyword == "f") { |
||||
const std::vector<std::string> indexTuples = Utility::String::splitWithoutEmptyParts(contents, ' '); |
||||
|
||||
/* Points */ |
||||
if(keyword == "p") { |
||||
/* Check that we don't mix the primitives in one mesh */ |
||||
if(primitive && primitive != MeshPrimitive::Points) { |
||||
Error() << "Trade::ObjImporter::mesh3D(): mixed primitive" << *primitive << "and" << MeshPrimitive::Points; |
||||
return std::nullopt; |
||||
} |
||||
|
||||
/* Check vertex count per primitive */ |
||||
if(indexTuples.size() != 1) { |
||||
Error() << "Trade::ObjImporter::mesh3D(): wrong index count for point"; |
||||
return std::nullopt; |
||||
} |
||||
|
||||
primitive = MeshPrimitive::Points; |
||||
|
||||
/* Lines */ |
||||
} else if(keyword == "l") { |
||||
/* Check that we don't mix the primitives in one mesh */ |
||||
if(primitive && primitive != MeshPrimitive::Lines) { |
||||
Error() << "Trade::ObjImporter::mesh3D(): mixed primitive" << *primitive << "and" << MeshPrimitive::Lines; |
||||
return std::nullopt; |
||||
} |
||||
|
||||
/* Check vertex count per primitive */ |
||||
if(indexTuples.size() != 2) { |
||||
Error() << "Trade::ObjImporter::mesh3D(): wrong index count for line"; |
||||
return std::nullopt; |
||||
} |
||||
|
||||
primitive = MeshPrimitive::Lines; |
||||
|
||||
/* Faces */ |
||||
} else if(keyword == "f") { |
||||
/* Check that we don't mix the primitives in one mesh */ |
||||
if(primitive && primitive != MeshPrimitive::Triangles) { |
||||
Error() << "Trade::ObjImporter::mesh3D(): mixed primitive" << *primitive << "and" << MeshPrimitive::Triangles; |
||||
return std::nullopt; |
||||
} |
||||
|
||||
/* Check vertex count per primitive */ |
||||
if(indexTuples.size() < 3) { |
||||
Error() << "Trade::ObjImporter::mesh3D(): wrong index count for triangle"; |
||||
return std::nullopt; |
||||
} else if(indexTuples.size() != 3) { |
||||
Error() << "Trade::ObjImporter::mesh3D(): polygons are not supported"; |
||||
return std::nullopt; |
||||
} |
||||
|
||||
primitive = MeshPrimitive::Triangles; |
||||
|
||||
} else CORRADE_ASSERT_UNREACHABLE(); |
||||
|
||||
for(const std::string& indexTuple: indexTuples) { |
||||
std::vector<std::string> indices = Utility::String::split(indexTuple, '/'); |
||||
if(indices.size() > 3) { |
||||
Error() << "Trade::ObjImporter::mesh3D(): invalid index data"; |
||||
return std::nullopt; |
||||
} |
||||
|
||||
/* Indices in OBJ file start from 1 */ |
||||
|
||||
/* Position indices */ |
||||
positionIndices.push_back(std::stoul(indices[0])-1); |
||||
|
||||
/* Texture coordinates */ |
||||
if(indices.size() == 2 || (indices.size() == 3 && !indices[1].empty())) |
||||
textureCoordinateIndices.push_back(std::stoul(indices[1])-1); |
||||
|
||||
/* Normal indices */ |
||||
if(indices.size() == 3) |
||||
normalIndices.push_back(std::stoul(indices[2])-1); |
||||
} |
||||
|
||||
/* Ignore unsupported keywords, error out on unknown keywords */ |
||||
} else if(![&keyword](){ |
||||
/* Using lambda to emulate for-else construct like in Python */ |
||||
for(const std::string expected: {"mtllib", "usemtl", "g", "s"}) |
||||
if(keyword == expected) return true; |
||||
return false; |
||||
}()) { |
||||
Error() << "Trade::ObjImporter::mesh3D(): unknown keyword" << keyword; |
||||
return std::nullopt; |
||||
} |
||||
|
||||
}} catch(std::exception) { |
||||
Error() << "Trade::ObjImporter::mesh3D(): error while converting numeric data"; |
||||
return std::nullopt; |
||||
} catch(...) { |
||||
/* Error message already printed */ |
||||
return std::nullopt; |
||||
} |
||||
|
||||
/* There should be at least indexed position data */ |
||||
if(positions.empty() || positionIndices.empty()) { |
||||
Error() << "Trade::ObjImporter::mesh3D(): incomplete position data"; |
||||
return std::nullopt; |
||||
} |
||||
|
||||
/* If there are index data, there should be also vertex data (and also the other way) */ |
||||
if(normals.empty() != normalIndices.empty()) { |
||||
Error() << "Trade::ObjImporter::mesh3D(): incomplete normal data"; |
||||
return std::nullopt; |
||||
} |
||||
if(textureCoordinates.empty() != textureCoordinateIndices.empty()) { |
||||
Error() << "Trade::ObjImporter::mesh3D(): incomplete texture coordinate data"; |
||||
return std::nullopt; |
||||
} |
||||
|
||||
/* All index arrays should have the same length */ |
||||
if(!normalIndices.empty() && normalIndices.size() != positionIndices.size()) { |
||||
CORRADE_INTERNAL_ASSERT(normalIndices.size() < positionIndices.size()); |
||||
Error() << "Trade::ObjImporter::mesh3D(): some normal indices are missing"; |
||||
return std::nullopt; |
||||
} |
||||
if(!textureCoordinates.empty() && textureCoordinateIndices.size() != positionIndices.size()) { |
||||
CORRADE_INTERNAL_ASSERT(textureCoordinateIndices.size() < positionIndices.size()); |
||||
Error() << "Trade::ObjImporter::mesh3D(): some texture coordinate indices are missing"; |
||||
return std::nullopt; |
||||
} |
||||
|
||||
/* Merge index arrays, if there aren't just the positions */ |
||||
std::vector<UnsignedInt> indices; |
||||
if(!normalIndices.empty() || !textureCoordinateIndices.empty()) { |
||||
std::vector<std::reference_wrapper<std::vector<UnsignedInt>>> arrays; |
||||
arrays.reserve(3); |
||||
arrays.push_back(positionIndices); |
||||
if(!normalIndices.empty()) arrays.push_back(normalIndices); |
||||
if(!textureCoordinateIndices.empty()) arrays.push_back(textureCoordinateIndices); |
||||
indices = MeshTools::combineIndexArrays(arrays); |
||||
|
||||
/* Reindex data arrays */ |
||||
try { |
||||
reindex(positionIndices, positions); |
||||
if(!normalIndices.empty()) reindex(normalIndices, normals.front()); |
||||
if(!textureCoordinateIndices.empty()) reindex(textureCoordinateIndices, textureCoordinates.front()); |
||||
} catch(...) { |
||||
/* Error message already printed */ |
||||
return std::nullopt; |
||||
} |
||||
|
||||
/* Otherwise just use the original position index array. Don't forget to
|
||||
check range */ |
||||
} else { |
||||
indices = std::move(positionIndices); |
||||
for(UnsignedInt i: indices) if(i >= positions.size()) { |
||||
Error() << "Trade::ObjImporter::mesh3D(): index out of range"; |
||||
return std::nullopt; |
||||
} |
||||
} |
||||
|
||||
return MeshData3D(*primitive, std::move(indices), {std::move(positions)}, std::move(normals), std::move(textureCoordinates)); |
||||
} |
||||
|
||||
}} |
||||
@ -0,0 +1,86 @@
|
||||
#ifndef Magnum_Trade_ObjImporter_h |
||||
#define Magnum_Trade_ObjImporter_h |
||||
/*
|
||||
This file is part of Magnum. |
||||
|
||||
Copyright © 2010, 2011, 2012, 2013, 2014 |
||||
Vladimír Vondruš <mosra@centrum.cz> |
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a |
||||
copy of this software and associated documentation files (the "Software"), |
||||
to deal in the Software without restriction, including without limitation |
||||
the rights to use, copy, modify, merge, publish, distribute, sublicense, |
||||
and/or sell copies of the Software, and to permit persons to whom the |
||||
Software is furnished to do so, subject to the following conditions: |
||||
|
||||
The above copyright notice and this permission notice shall be included |
||||
in all copies or substantial portions of the Software. |
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
||||
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
||||
DEALINGS IN THE SOFTWARE. |
||||
*/ |
||||
|
||||
/** @file
|
||||
* @brief Class @ref Magnum::Trade::ObjImporter |
||||
*/ |
||||
|
||||
#include "Magnum/Trade/AbstractImporter.h" |
||||
|
||||
namespace Magnum { namespace Trade { |
||||
|
||||
/**
|
||||
@brief OBJ importer plugin |
||||
|
||||
Supported features: |
||||
- multiple objects |
||||
- vertex positions, normals and 2D texture coordinates |
||||
- triangles, lines and points |
||||
|
||||
Polygons (quads etc.), automatic normal generation and material properties are |
||||
currently not supported. |
||||
|
||||
This plugin is built if `WITH_OBJIMPORTER` is enabled when building %Magnum. To |
||||
use dynamic plugin, you need to load `%ObjImporter` plugin from |
||||
`MAGNUM_PLUGINS_IMPORTER_DIR`. To use static plugin or use this as a dependency |
||||
of another plugin, you need to request `%ObjImporter` component of `%Magnum` |
||||
package in CMake and link to `${MAGNUM_OBJIMPORTER_LIBRARIES}`. See |
||||
@ref building, @ref cmake and @ref plugins for more information. |
||||
*/ |
||||
class ObjImporter: public AbstractImporter { |
||||
public: |
||||
/** @brief Default constructor */ |
||||
explicit ObjImporter(); |
||||
|
||||
/** @brief Plugin manager constructor */ |
||||
explicit ObjImporter(PluginManager::AbstractManager& manager, std::string plugin); |
||||
|
||||
~ObjImporter(); |
||||
|
||||
private: |
||||
struct File; |
||||
|
||||
Features doFeatures() const override; |
||||
|
||||
bool doIsOpened() const override; |
||||
void doOpenData(Containers::ArrayReference<const unsigned char> data) override; |
||||
void doOpenFile(const std::string& filename) override; |
||||
void doClose() override; |
||||
|
||||
UnsignedInt doMesh3DCount() const override; |
||||
Int doMesh3DForName(const std::string& name) override; |
||||
std::string doMesh3DName(UnsignedInt id) override; |
||||
std::optional<MeshData3D> doMesh3D(UnsignedInt id) override; |
||||
|
||||
void parseMeshNames(); |
||||
|
||||
std::unique_ptr<File> _file; |
||||
}; |
||||
|
||||
}} |
||||
|
||||
#endif |
||||
@ -0,0 +1,31 @@
|
||||
# |
||||
# This file is part of Magnum. |
||||
# |
||||
# Copyright © 2010, 2011, 2012, 2013, 2014 |
||||
# Vladimír Vondruš <mosra@centrum.cz> |
||||
# |
||||
# Permission is hereby granted, free of charge, to any person obtaining a |
||||
# copy of this software and associated documentation files (the "Software"), |
||||
# to deal in the Software without restriction, including without limitation |
||||
# the rights to use, copy, modify, merge, publish, distribute, sublicense, |
||||
# and/or sell copies of the Software, and to permit persons to whom the |
||||
# Software is furnished to do so, subject to the following conditions: |
||||
# |
||||
# The above copyright notice and this permission notice shall be included |
||||
# in all copies or substantial portions of the Software. |
||||
# |
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
||||
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
||||
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
||||
# DEALINGS IN THE SOFTWARE. |
||||
# |
||||
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/configure.h.cmake |
||||
${CMAKE_CURRENT_BINARY_DIR}/configure.h) |
||||
|
||||
include_directories(BEFORE ${CMAKE_CURRENT_BINARY_DIR}) |
||||
|
||||
corrade_add_test(ObjImporterTest Test.cpp LIBRARIES ObjImporterTestLib) |
||||
@ -0,0 +1,737 @@
|
||||
/*
|
||||
This file is part of Magnum. |
||||
|
||||
Copyright © 2010, 2011, 2012, 2013, 2014 |
||||
Vladimír Vondruš <mosra@centrum.cz> |
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a |
||||
copy of this software and associated documentation files (the "Software"), |
||||
to deal in the Software without restriction, including without limitation |
||||
the rights to use, copy, modify, merge, publish, distribute, sublicense, |
||||
and/or sell copies of the Software, and to permit persons to whom the |
||||
Software is furnished to do so, subject to the following conditions: |
||||
|
||||
The above copyright notice and this permission notice shall be included |
||||
in all copies or substantial portions of the Software. |
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
||||
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
||||
DEALINGS IN THE SOFTWARE. |
||||
*/ |
||||
|
||||
#include <sstream> |
||||
#include <Corrade/TestSuite/Tester.h> |
||||
#include <Corrade/Utility/Directory.h> |
||||
|
||||
#include "Magnum/Mesh.h" |
||||
#include "Magnum/Math/Vector3.h" |
||||
#include "Magnum/Trade/MeshData3D.h" |
||||
#include "MagnumPlugins/ObjImporter/ObjImporter.h" |
||||
|
||||
#include "configure.h" |
||||
|
||||
namespace Magnum { namespace Trade { namespace Test { |
||||
|
||||
class ObjImporterTest: public TestSuite::Tester { |
||||
public: |
||||
explicit ObjImporterTest(); |
||||
|
||||
void pointMesh(); |
||||
void lineMesh(); |
||||
void triangleMesh(); |
||||
void mixedPrimitives(); |
||||
|
||||
void positionsOnly(); |
||||
void textureCoordinates(); |
||||
void normals(); |
||||
void textureCoordinatesNormals(); |
||||
|
||||
void emptyFile(); |
||||
void unnamedMesh(); |
||||
void namedMesh(); |
||||
void moreMeshes(); |
||||
void unnamedFirstMesh(); |
||||
|
||||
void wrongFloat(); |
||||
void wrongInteger(); |
||||
void unmergedIndexOutOfRange(); |
||||
void mergedIndexOutOfRange(); |
||||
void zeroIndex(); |
||||
|
||||
void explicitOptionalPositionCoordinate(); |
||||
void explicitOptionalTextureCoordinate(); |
||||
void unsupportedOptionalPositionCoordinate(); |
||||
void unsupportedOptionalTextureCoordinate(); |
||||
|
||||
void shortFloatData(); |
||||
void longFloatData(); |
||||
void longOptionalFloatData(); |
||||
|
||||
void longIndexData(); |
||||
void wrongPointIndexData(); |
||||
void wrongLineIndexData(); |
||||
void wrongTriangleIndexData(); |
||||
void polygonIndexData(); |
||||
|
||||
void missingPositionData(); |
||||
void missingNormalData(); |
||||
void missingTextureCoordinateData(); |
||||
void missingPositionIndices(); |
||||
void missingNormalIndices(); |
||||
void missingTextureCoordinateIndices(); |
||||
|
||||
void wrongTextureCoordinateIndexCount(); |
||||
void wrongNormalIndexCount(); |
||||
|
||||
void unsupportedKeyword(); |
||||
void unknownKeyword(); |
||||
}; |
||||
|
||||
ObjImporterTest::ObjImporterTest() { |
||||
addTests({&ObjImporterTest::pointMesh, |
||||
&ObjImporterTest::lineMesh, |
||||
&ObjImporterTest::triangleMesh, |
||||
&ObjImporterTest::mixedPrimitives, |
||||
|
||||
&ObjImporterTest::positionsOnly, |
||||
&ObjImporterTest::textureCoordinates, |
||||
&ObjImporterTest::normals, |
||||
&ObjImporterTest::textureCoordinatesNormals, |
||||
|
||||
&ObjImporterTest::emptyFile, |
||||
&ObjImporterTest::unnamedMesh, |
||||
&ObjImporterTest::namedMesh, |
||||
&ObjImporterTest::moreMeshes, |
||||
&ObjImporterTest::unnamedFirstMesh, |
||||
|
||||
&ObjImporterTest::wrongFloat, |
||||
&ObjImporterTest::wrongInteger, |
||||
&ObjImporterTest::unmergedIndexOutOfRange, |
||||
&ObjImporterTest::mergedIndexOutOfRange, |
||||
&ObjImporterTest::zeroIndex, |
||||
|
||||
&ObjImporterTest::explicitOptionalPositionCoordinate, |
||||
&ObjImporterTest::explicitOptionalTextureCoordinate, |
||||
&ObjImporterTest::unsupportedOptionalPositionCoordinate, |
||||
&ObjImporterTest::unsupportedOptionalTextureCoordinate, |
||||
|
||||
&ObjImporterTest::shortFloatData, |
||||
&ObjImporterTest::longFloatData, |
||||
&ObjImporterTest::longOptionalFloatData, |
||||
|
||||
&ObjImporterTest::longIndexData, |
||||
&ObjImporterTest::wrongPointIndexData, |
||||
&ObjImporterTest::wrongLineIndexData, |
||||
&ObjImporterTest::wrongTriangleIndexData, |
||||
|
||||
&ObjImporterTest::missingPositionData, |
||||
&ObjImporterTest::missingNormalData, |
||||
&ObjImporterTest::missingTextureCoordinateData, |
||||
&ObjImporterTest::missingPositionIndices, |
||||
&ObjImporterTest::missingNormalIndices, |
||||
&ObjImporterTest::missingTextureCoordinateIndices, |
||||
|
||||
&ObjImporterTest::wrongTextureCoordinateIndexCount, |
||||
&ObjImporterTest::wrongNormalIndexCount, |
||||
|
||||
&ObjImporterTest::unsupportedKeyword, |
||||
&ObjImporterTest::unknownKeyword}); |
||||
} |
||||
|
||||
void ObjImporterTest::pointMesh() { |
||||
ObjImporter importer; |
||||
CORRADE_VERIFY(importer.openFile(Utility::Directory::join(OBJIMPORTER_TEST_DIR, "pointMesh.obj"))); |
||||
CORRADE_COMPARE(importer.mesh3DCount(), 1); |
||||
|
||||
const std::optional<MeshData3D> data = importer.mesh3D(0); |
||||
CORRADE_VERIFY(data); |
||||
CORRADE_COMPARE(data->primitive(), MeshPrimitive::Points); |
||||
CORRADE_COMPARE(data->positionArrayCount(), 1); |
||||
CORRADE_COMPARE(data->positions(0), (std::vector<Vector3>{ |
||||
{0.5f, 2.0f, 3.0f}, |
||||
{0.0f, 1.5f, 1.0f}, |
||||
{2.0f, 3.0f, 5.0f} |
||||
})); |
||||
CORRADE_COMPARE(data->indices(), (std::vector<UnsignedInt>{ |
||||
0, 2, 1, 0 |
||||
})); |
||||
} |
||||
|
||||
void ObjImporterTest::lineMesh() { |
||||
ObjImporter importer; |
||||
CORRADE_VERIFY(importer.openFile(Utility::Directory::join(OBJIMPORTER_TEST_DIR, "lineMesh.obj"))); |
||||
CORRADE_COMPARE(importer.mesh3DCount(), 1); |
||||
|
||||
const std::optional<MeshData3D> data = importer.mesh3D(0); |
||||
CORRADE_VERIFY(data); |
||||
CORRADE_COMPARE(data->primitive(), MeshPrimitive::Lines); |
||||
CORRADE_COMPARE(data->positionArrayCount(), 1); |
||||
CORRADE_COMPARE(data->positions(0), (std::vector<Vector3>{ |
||||
{0.5f, 2.0f, 3.0f}, |
||||
{0.0f, 1.5f, 1.0f}, |
||||
{2.0f, 3.0f, 5.0f} |
||||
})); |
||||
CORRADE_COMPARE(data->indices(), (std::vector<UnsignedInt>{ |
||||
0, 1, 1, 2 |
||||
})); |
||||
} |
||||
|
||||
void ObjImporterTest::triangleMesh() { |
||||
ObjImporter importer; |
||||
CORRADE_VERIFY(importer.openFile(Utility::Directory::join(OBJIMPORTER_TEST_DIR, "triangleMesh.obj"))); |
||||
CORRADE_COMPARE(importer.mesh3DCount(), 1); |
||||
|
||||
const std::optional<MeshData3D> data = importer.mesh3D(0); |
||||
CORRADE_VERIFY(data); |
||||
CORRADE_COMPARE(data->primitive(), MeshPrimitive::Triangles); |
||||
CORRADE_COMPARE(data->positionArrayCount(), 1); |
||||
CORRADE_COMPARE(data->positions(0), (std::vector<Vector3>{ |
||||
{0.5f, 2.0f, 3.0f}, |
||||
{0.0f, 1.5f, 1.0f}, |
||||
{2.0f, 3.0f, 5.0f}, |
||||
{2.5f, 0.0f, 1.0f} |
||||
})); |
||||
CORRADE_COMPARE(data->indices(), (std::vector<UnsignedInt>{ |
||||
0, 1, 2, 3, 1, 0 |
||||
})); |
||||
} |
||||
|
||||
void ObjImporterTest::mixedPrimitives() { |
||||
ObjImporter importer; |
||||
CORRADE_VERIFY(importer.openFile(Utility::Directory::join(OBJIMPORTER_TEST_DIR, "mixedPrimitives.obj"))); |
||||
CORRADE_COMPARE(importer.mesh3DCount(), 1); |
||||
|
||||
std::ostringstream out; |
||||
Error::setOutput(&out); |
||||
CORRADE_VERIFY(!importer.mesh3D(0)); |
||||
CORRADE_COMPARE(out.str(), "Trade::ObjImporter::mesh3D(): mixed primitive MeshPrimitive::Points and MeshPrimitive::Lines\n"); |
||||
} |
||||
|
||||
void ObjImporterTest::positionsOnly() { |
||||
ObjImporter importer; |
||||
CORRADE_VERIFY(importer.openFile(Utility::Directory::join(OBJIMPORTER_TEST_DIR, "triangleMesh.obj"))); |
||||
CORRADE_COMPARE(importer.mesh3DCount(), 1); |
||||
|
||||
const std::optional<MeshData3D> data = importer.mesh3D(0); |
||||
CORRADE_VERIFY(data); |
||||
CORRADE_COMPARE(data->positionArrayCount(), 1); |
||||
CORRADE_VERIFY(!data->hasNormals()); |
||||
CORRADE_VERIFY(!data->hasTextureCoords2D()); |
||||
} |
||||
|
||||
void ObjImporterTest::textureCoordinates() { |
||||
ObjImporter importer; |
||||
CORRADE_VERIFY(importer.openFile(Utility::Directory::join(OBJIMPORTER_TEST_DIR, "textureCoordinates.obj"))); |
||||
CORRADE_COMPARE(importer.mesh3DCount(), 1); |
||||
|
||||
const std::optional<MeshData3D> data = importer.mesh3D(0); |
||||
CORRADE_VERIFY(data); |
||||
CORRADE_COMPARE(data->primitive(), MeshPrimitive::Lines); |
||||
CORRADE_COMPARE(data->positionArrayCount(), 1); |
||||
CORRADE_VERIFY(!data->hasNormals()); |
||||
CORRADE_COMPARE(data->textureCoords2DArrayCount(), 1); |
||||
CORRADE_COMPARE(data->positions(0), (std::vector<Vector3>{ |
||||
{0.5f, 2.0f, 3.0f}, |
||||
{0.0f, 1.5f, 1.0f}, |
||||
{0.5f, 2.0f, 3.0f}, |
||||
{0.0f, 1.5f, 1.0f} |
||||
})); |
||||
CORRADE_COMPARE(data->textureCoords2D(0), (std::vector<Vector2>{ |
||||
{1.0f, 0.5f}, |
||||
{1.0f, 0.5f}, |
||||
{0.5f, 1.0f}, |
||||
{0.5f, 1.0f} |
||||
})); |
||||
CORRADE_COMPARE(data->indices(), (std::vector<UnsignedInt>{ |
||||
0, 1, 2, 3, 1, 0 |
||||
})); |
||||
} |
||||
|
||||
void ObjImporterTest::normals() { |
||||
ObjImporter importer; |
||||
CORRADE_VERIFY(importer.openFile(Utility::Directory::join(OBJIMPORTER_TEST_DIR, "normals.obj"))); |
||||
CORRADE_COMPARE(importer.mesh3DCount(), 1); |
||||
|
||||
const std::optional<MeshData3D> data = importer.mesh3D(0); |
||||
CORRADE_VERIFY(data); |
||||
CORRADE_COMPARE(data->primitive(), MeshPrimitive::Lines); |
||||
CORRADE_COMPARE(data->positionArrayCount(), 1); |
||||
CORRADE_VERIFY(!data->hasTextureCoords2D()); |
||||
CORRADE_COMPARE(data->normalArrayCount(), 1); |
||||
CORRADE_COMPARE(data->positions(0), (std::vector<Vector3>{ |
||||
{0.5f, 2.0f, 3.0f}, |
||||
{0.0f, 1.5f, 1.0f}, |
||||
{0.5f, 2.0f, 3.0f}, |
||||
{0.0f, 1.5f, 1.0f} |
||||
})); |
||||
CORRADE_COMPARE(data->normals(0), (std::vector<Vector3>{ |
||||
{1.0f, 0.5f, 3.5f}, |
||||
{1.0f, 0.5f, 3.5f}, |
||||
{0.5f, 1.0f, 0.5f}, |
||||
{0.5f, 1.0f, 0.5f} |
||||
})); |
||||
CORRADE_COMPARE(data->indices(), (std::vector<UnsignedInt>{ |
||||
0, 1, 2, 3, 1, 0 |
||||
})); |
||||
} |
||||
|
||||
void ObjImporterTest::textureCoordinatesNormals() { |
||||
ObjImporter importer; |
||||
CORRADE_VERIFY(importer.openFile(Utility::Directory::join(OBJIMPORTER_TEST_DIR, "textureCoordinatesNormals.obj"))); |
||||
CORRADE_COMPARE(importer.mesh3DCount(), 1); |
||||
|
||||
const std::optional<MeshData3D> data = importer.mesh3D(0); |
||||
CORRADE_VERIFY(data); |
||||
CORRADE_COMPARE(data->primitive(), MeshPrimitive::Lines); |
||||
CORRADE_COMPARE(data->positionArrayCount(), 1); |
||||
CORRADE_COMPARE(data->textureCoords2DArrayCount(), 1); |
||||
CORRADE_COMPARE(data->normalArrayCount(), 1); |
||||
CORRADE_COMPARE(data->positions(0), (std::vector<Vector3>{ |
||||
{0.5f, 2.0f, 3.0f}, |
||||
{0.0f, 1.5f, 1.0f}, |
||||
{0.5f, 2.0f, 3.0f}, |
||||
{0.0f, 1.5f, 1.0f}, |
||||
{0.0f, 1.5f, 1.0f} |
||||
})); |
||||
CORRADE_COMPARE(data->textureCoords2D(0), (std::vector<Vector2>{ |
||||
{1.0f, 0.5f}, |
||||
{1.0f, 0.5f}, |
||||
{0.5f, 1.0f}, |
||||
{0.5f, 1.0f}, |
||||
{0.5f, 1.0f} |
||||
})); |
||||
CORRADE_COMPARE(data->normals(0), (std::vector<Vector3>{ |
||||
{1.0f, 0.5f, 3.5f}, |
||||
{0.5f, 1.0f, 0.5f}, |
||||
{0.5f, 1.0f, 0.5f}, |
||||
{1.0f, 0.5f, 3.5f}, |
||||
{0.5f, 1.0f, 0.5f} |
||||
})); |
||||
CORRADE_COMPARE(data->indices(), (std::vector<UnsignedInt>{ |
||||
0, 1, 2, 3, 1, 0, 4, 2 |
||||
})); |
||||
} |
||||
|
||||
void ObjImporterTest::emptyFile() { |
||||
ObjImporter importer; |
||||
CORRADE_VERIFY(importer.openFile(Utility::Directory::join(OBJIMPORTER_TEST_DIR, "emptyFile.obj"))); |
||||
CORRADE_COMPARE(importer.mesh3DCount(), 1); |
||||
} |
||||
|
||||
void ObjImporterTest::unnamedMesh() { |
||||
ObjImporter importer; |
||||
CORRADE_VERIFY(importer.openFile(Utility::Directory::join(OBJIMPORTER_TEST_DIR, "emptyFile.obj"))); |
||||
CORRADE_COMPARE(importer.mesh3DCount(), 1); |
||||
CORRADE_COMPARE(importer.mesh3DName(0), ""); |
||||
CORRADE_COMPARE(importer.mesh3DForName(""), -1); |
||||
} |
||||
|
||||
void ObjImporterTest::namedMesh() { |
||||
ObjImporter importer; |
||||
CORRADE_VERIFY(importer.openFile(Utility::Directory::join(OBJIMPORTER_TEST_DIR, "namedMesh.obj"))); |
||||
CORRADE_COMPARE(importer.mesh3DCount(), 1); |
||||
CORRADE_COMPARE(importer.mesh3DName(0), "MyMesh"); |
||||
CORRADE_COMPARE(importer.mesh3DForName("MyMesh"), 0); |
||||
} |
||||
|
||||
void ObjImporterTest::moreMeshes() { |
||||
ObjImporter importer; |
||||
CORRADE_VERIFY(importer.openFile(Utility::Directory::join(OBJIMPORTER_TEST_DIR, "moreMeshes.obj"))); |
||||
CORRADE_COMPARE(importer.mesh3DCount(), 3); |
||||
|
||||
CORRADE_COMPARE(importer.mesh3DName(0), "PointMesh"); |
||||
CORRADE_COMPARE(importer.mesh3DForName("PointMesh"), 0); |
||||
const std::optional<MeshData3D> data = importer.mesh3D(0); |
||||
CORRADE_VERIFY(data); |
||||
CORRADE_COMPARE(data->primitive(), MeshPrimitive::Points); |
||||
CORRADE_COMPARE(data->positionArrayCount(), 1); |
||||
CORRADE_COMPARE(data->positions(0), (std::vector<Vector3>{ |
||||
{0.5f, 2.0f, 3.0f}, |
||||
{0.0f, 1.5f, 1.0f} |
||||
})); |
||||
CORRADE_COMPARE(data->indices(), (std::vector<UnsignedInt>{ |
||||
0, 1 |
||||
})); |
||||
|
||||
CORRADE_COMPARE(importer.mesh3DName(1), "LineMesh"); |
||||
CORRADE_COMPARE(importer.mesh3DForName("LineMesh"), 1); |
||||
const std::optional<MeshData3D> data1 = importer.mesh3D(1); |
||||
CORRADE_VERIFY(data1); |
||||
CORRADE_COMPARE(data1->primitive(), MeshPrimitive::Lines); |
||||
CORRADE_COMPARE(data1->positionArrayCount(), 1); |
||||
CORRADE_COMPARE(data1->positions(0), (std::vector<Vector3>{ |
||||
{0.5f, 2.0f, 3.0f}, |
||||
{0.0f, 1.5f, 1.0f} |
||||
})); |
||||
CORRADE_COMPARE(data1->indices(), (std::vector<UnsignedInt>{ |
||||
0, 1, 1, 0 |
||||
})); |
||||
|
||||
CORRADE_COMPARE(importer.mesh3DName(2), "TriangleMesh"); |
||||
CORRADE_COMPARE(importer.mesh3DForName("TriangleMesh"), 2); |
||||
const std::optional<MeshData3D> data2 = importer.mesh3D(2); |
||||
CORRADE_VERIFY(data2); |
||||
CORRADE_COMPARE(data2->primitive(), MeshPrimitive::Triangles); |
||||
CORRADE_COMPARE(data2->positionArrayCount(), 1); |
||||
CORRADE_COMPARE(data2->positions(0), (std::vector<Vector3>{ |
||||
{0.5f, 2.0f, 3.0f}, |
||||
{0.0f, 1.5f, 1.0f}, |
||||
{2.0f, 3.0f, 5.5f} |
||||
})); |
||||
CORRADE_COMPARE(data2->indices(), (std::vector<UnsignedInt>{ |
||||
0, 1, 2, 2, 1, 0 |
||||
})); |
||||
} |
||||
|
||||
void ObjImporterTest::unnamedFirstMesh() { |
||||
ObjImporter importer; |
||||
CORRADE_VERIFY(importer.openFile(Utility::Directory::join(OBJIMPORTER_TEST_DIR, "unnamedFirstMesh.obj"))); |
||||
CORRADE_COMPARE(importer.mesh3DCount(), 2); |
||||
|
||||
CORRADE_COMPARE(importer.mesh3DName(0), ""); |
||||
CORRADE_COMPARE(importer.mesh3DForName(""), -1); |
||||
|
||||
CORRADE_COMPARE(importer.mesh3DName(1), "SecondMesh"); |
||||
CORRADE_COMPARE(importer.mesh3DForName("SecondMesh"), 1); |
||||
} |
||||
|
||||
void ObjImporterTest::wrongFloat() { |
||||
ObjImporter importer; |
||||
CORRADE_VERIFY(importer.openFile(Utility::Directory::join(OBJIMPORTER_TEST_DIR, "wrongNumbers.obj"))); |
||||
const Int id = importer.mesh3DForName("WrongFloat"); |
||||
CORRADE_VERIFY(id > -1); |
||||
|
||||
std::ostringstream out; |
||||
Error::setOutput(&out); |
||||
CORRADE_VERIFY(!importer.mesh3D(id)); |
||||
CORRADE_COMPARE(out.str(), "Trade::ObjImporter::mesh3D(): error while converting numeric data\n"); |
||||
} |
||||
|
||||
void ObjImporterTest::wrongInteger() { |
||||
ObjImporter importer; |
||||
CORRADE_VERIFY(importer.openFile(Utility::Directory::join(OBJIMPORTER_TEST_DIR, "wrongNumbers.obj"))); |
||||
const Int id = importer.mesh3DForName("WrongInteger"); |
||||
CORRADE_VERIFY(id > -1); |
||||
|
||||
std::ostringstream out; |
||||
Error::setOutput(&out); |
||||
CORRADE_VERIFY(!importer.mesh3D(id)); |
||||
CORRADE_COMPARE(out.str(), "Trade::ObjImporter::mesh3D(): error while converting numeric data\n"); |
||||
} |
||||
|
||||
void ObjImporterTest::unmergedIndexOutOfRange() { |
||||
ObjImporter importer; |
||||
CORRADE_VERIFY(importer.openFile(Utility::Directory::join(OBJIMPORTER_TEST_DIR, "wrongNumbers.obj"))); |
||||
const Int id = importer.mesh3DForName("PositionIndexOutOfRange"); |
||||
CORRADE_VERIFY(id > -1); |
||||
|
||||
std::ostringstream out; |
||||
Error::setOutput(&out); |
||||
CORRADE_VERIFY(!importer.mesh3D(id)); |
||||
CORRADE_COMPARE(out.str(), "Trade::ObjImporter::mesh3D(): index out of range\n"); |
||||
} |
||||
|
||||
void ObjImporterTest::mergedIndexOutOfRange() { |
||||
ObjImporter importer; |
||||
CORRADE_VERIFY(importer.openFile(Utility::Directory::join(OBJIMPORTER_TEST_DIR, "wrongNumbers.obj"))); |
||||
const Int id = importer.mesh3DForName("TextureIndexOutOfRange"); |
||||
CORRADE_VERIFY(id > -1); |
||||
|
||||
std::ostringstream out; |
||||
Error::setOutput(&out); |
||||
CORRADE_VERIFY(!importer.mesh3D(id)); |
||||
CORRADE_COMPARE(out.str(), "Trade::ObjImporter::mesh3D(): index out of range\n"); |
||||
} |
||||
|
||||
void ObjImporterTest::zeroIndex() { |
||||
ObjImporter importer; |
||||
CORRADE_VERIFY(importer.openFile(Utility::Directory::join(OBJIMPORTER_TEST_DIR, "wrongNumbers.obj"))); |
||||
const Int id = importer.mesh3DForName("ZeroIndex"); |
||||
CORRADE_VERIFY(id > -1); |
||||
|
||||
std::ostringstream out; |
||||
Error::setOutput(&out); |
||||
CORRADE_VERIFY(!importer.mesh3D(id)); |
||||
CORRADE_COMPARE(out.str(), "Trade::ObjImporter::mesh3D(): index out of range\n"); |
||||
} |
||||
|
||||
void ObjImporterTest::explicitOptionalPositionCoordinate() { |
||||
ObjImporter importer; |
||||
CORRADE_VERIFY(importer.openFile(Utility::Directory::join(OBJIMPORTER_TEST_DIR, "optionalCoordinates.obj"))); |
||||
const Int id = importer.mesh3DForName("SupportedPositionW"); |
||||
CORRADE_VERIFY(id > -1); |
||||
|
||||
const std::optional<MeshData3D> data = importer.mesh3D(id); |
||||
CORRADE_VERIFY(data); |
||||
CORRADE_COMPARE(data->positionArrayCount(), 1); |
||||
CORRADE_COMPARE(data->positions(0), (std::vector<Vector3>{ |
||||
{1.5f, 2.0f, 3.0f} |
||||
})); |
||||
} |
||||
|
||||
void ObjImporterTest::explicitOptionalTextureCoordinate() { |
||||
ObjImporter importer; |
||||
CORRADE_VERIFY(importer.openFile(Utility::Directory::join(OBJIMPORTER_TEST_DIR, "optionalCoordinates.obj"))); |
||||
const Int id = importer.mesh3DForName("SupportedTextureW"); |
||||
CORRADE_VERIFY(id > -1); |
||||
|
||||
const std::optional<MeshData3D> data = importer.mesh3D(id); |
||||
CORRADE_VERIFY(data); |
||||
CORRADE_COMPARE(data->textureCoords2DArrayCount(), 1); |
||||
CORRADE_COMPARE(data->textureCoords2D(0), (std::vector<Vector2>{ |
||||
{0.5f, 0.7f} |
||||
})); |
||||
} |
||||
|
||||
void ObjImporterTest::unsupportedOptionalPositionCoordinate() { |
||||
ObjImporter importer; |
||||
CORRADE_VERIFY(importer.openFile(Utility::Directory::join(OBJIMPORTER_TEST_DIR, "optionalCoordinates.obj"))); |
||||
const Int id = importer.mesh3DForName("UnsupportedPositionW"); |
||||
CORRADE_VERIFY(id > -1); |
||||
|
||||
std::ostringstream out; |
||||
Error::setOutput(&out); |
||||
CORRADE_VERIFY(!importer.mesh3D(id)); |
||||
CORRADE_COMPARE(out.str(), "Trade::ObjImporter::mesh3D(): homogeneous coordinates are not supported\n"); |
||||
} |
||||
|
||||
void ObjImporterTest::unsupportedOptionalTextureCoordinate() { |
||||
ObjImporter importer; |
||||
CORRADE_VERIFY(importer.openFile(Utility::Directory::join(OBJIMPORTER_TEST_DIR, "optionalCoordinates.obj"))); |
||||
const Int id = importer.mesh3DForName("UnsupportedTextureW"); |
||||
CORRADE_VERIFY(id > -1); |
||||
|
||||
std::ostringstream out; |
||||
Error::setOutput(&out); |
||||
CORRADE_VERIFY(!importer.mesh3D(id)); |
||||
CORRADE_COMPARE(out.str(), "Trade::ObjImporter::mesh3D(): 3D texture coordinates are not supported\n"); |
||||
} |
||||
|
||||
void ObjImporterTest::shortFloatData() { |
||||
ObjImporter importer; |
||||
CORRADE_VERIFY(importer.openFile(Utility::Directory::join(OBJIMPORTER_TEST_DIR, "wrongNumberCount.obj"))); |
||||
const Int id = importer.mesh3DForName("ShortFloat"); |
||||
CORRADE_VERIFY(id > -1); |
||||
|
||||
std::ostringstream out; |
||||
Error::setOutput(&out); |
||||
CORRADE_VERIFY(!importer.mesh3D(id)); |
||||
CORRADE_COMPARE(out.str(), "Trade::ObjImporter::mesh3D(): invalid float array size\n"); |
||||
} |
||||
|
||||
void ObjImporterTest::longFloatData() { |
||||
ObjImporter importer; |
||||
CORRADE_VERIFY(importer.openFile(Utility::Directory::join(OBJIMPORTER_TEST_DIR, "wrongNumberCount.obj"))); |
||||
const Int id = importer.mesh3DForName("LongFloat"); |
||||
CORRADE_VERIFY(id > -1); |
||||
|
||||
std::ostringstream out; |
||||
Error::setOutput(&out); |
||||
CORRADE_VERIFY(!importer.mesh3D(id)); |
||||
CORRADE_COMPARE(out.str(), "Trade::ObjImporter::mesh3D(): invalid float array size\n"); |
||||
} |
||||
|
||||
void ObjImporterTest::longOptionalFloatData() { |
||||
ObjImporter importer; |
||||
CORRADE_VERIFY(importer.openFile(Utility::Directory::join(OBJIMPORTER_TEST_DIR, "wrongNumberCount.obj"))); |
||||
const Int id = importer.mesh3DForName("LongOptionalFloat"); |
||||
CORRADE_VERIFY(id > -1); |
||||
|
||||
std::ostringstream out; |
||||
Error::setOutput(&out); |
||||
CORRADE_VERIFY(!importer.mesh3D(id)); |
||||
CORRADE_COMPARE(out.str(), "Trade::ObjImporter::mesh3D(): invalid float array size\n"); |
||||
} |
||||
|
||||
void ObjImporterTest::longIndexData() { |
||||
ObjImporter importer; |
||||
CORRADE_VERIFY(importer.openFile(Utility::Directory::join(OBJIMPORTER_TEST_DIR, "wrongNumberCount.obj"))); |
||||
const Int id = importer.mesh3DForName("InvalidIndices"); |
||||
CORRADE_VERIFY(id > -1); |
||||
|
||||
std::ostringstream out; |
||||
Error::setOutput(&out); |
||||
CORRADE_VERIFY(!importer.mesh3D(id)); |
||||
CORRADE_COMPARE(out.str(), "Trade::ObjImporter::mesh3D(): invalid index data\n"); |
||||
} |
||||
|
||||
void ObjImporterTest::wrongPointIndexData() { |
||||
ObjImporter importer; |
||||
CORRADE_VERIFY(importer.openFile(Utility::Directory::join(OBJIMPORTER_TEST_DIR, "wrongNumberCount.obj"))); |
||||
const Int id = importer.mesh3DForName("WrongPointIndices"); |
||||
CORRADE_VERIFY(id > -1); |
||||
|
||||
std::ostringstream out; |
||||
Error::setOutput(&out); |
||||
CORRADE_VERIFY(!importer.mesh3D(id)); |
||||
CORRADE_COMPARE(out.str(), "Trade::ObjImporter::mesh3D(): wrong index count for point\n"); |
||||
} |
||||
|
||||
void ObjImporterTest::wrongLineIndexData() { |
||||
ObjImporter importer; |
||||
CORRADE_VERIFY(importer.openFile(Utility::Directory::join(OBJIMPORTER_TEST_DIR, "wrongNumberCount.obj"))); |
||||
const Int id = importer.mesh3DForName("WrongLineIndices"); |
||||
CORRADE_VERIFY(id > -1); |
||||
|
||||
std::ostringstream out; |
||||
Error::setOutput(&out); |
||||
CORRADE_VERIFY(!importer.mesh3D(id)); |
||||
CORRADE_COMPARE(out.str(), "Trade::ObjImporter::mesh3D(): wrong index count for line\n"); |
||||
} |
||||
|
||||
void ObjImporterTest::wrongTriangleIndexData() { |
||||
ObjImporter importer; |
||||
CORRADE_VERIFY(importer.openFile(Utility::Directory::join(OBJIMPORTER_TEST_DIR, "wrongNumberCount.obj"))); |
||||
const Int id = importer.mesh3DForName("WrongTriangleIndices"); |
||||
CORRADE_VERIFY(id > -1); |
||||
|
||||
std::ostringstream out; |
||||
Error::setOutput(&out); |
||||
CORRADE_VERIFY(!importer.mesh3D(id)); |
||||
CORRADE_COMPARE(out.str(), "Trade::ObjImporter::mesh3D(): wrong index count for triangle\n"); |
||||
} |
||||
|
||||
void ObjImporterTest::polygonIndexData() { |
||||
ObjImporter importer; |
||||
CORRADE_VERIFY(importer.openFile(Utility::Directory::join(OBJIMPORTER_TEST_DIR, "wrongNumberCount.obj"))); |
||||
const Int id = importer.mesh3DForName("PolygonIndices"); |
||||
CORRADE_VERIFY(id > -1); |
||||
|
||||
std::ostringstream out; |
||||
Error::setOutput(&out); |
||||
CORRADE_VERIFY(!importer.mesh3D(id)); |
||||
CORRADE_COMPARE(out.str(), "Trade::ObjImporter::mesh3D(): polygons are not supported\n"); |
||||
} |
||||
|
||||
void ObjImporterTest::missingPositionData() { |
||||
ObjImporter importer; |
||||
CORRADE_VERIFY(importer.openFile(Utility::Directory::join(OBJIMPORTER_TEST_DIR, "missingData.obj"))); |
||||
const Int id = importer.mesh3DForName("MissingPositionData"); |
||||
CORRADE_VERIFY(id > -1); |
||||
|
||||
std::ostringstream out; |
||||
Error::setOutput(&out); |
||||
CORRADE_VERIFY(!importer.mesh3D(id)); |
||||
CORRADE_COMPARE(out.str(), "Trade::ObjImporter::mesh3D(): incomplete position data\n"); |
||||
} |
||||
|
||||
void ObjImporterTest::missingPositionIndices() { |
||||
ObjImporter importer; |
||||
CORRADE_VERIFY(importer.openFile(Utility::Directory::join(OBJIMPORTER_TEST_DIR, "missingData.obj"))); |
||||
const Int id = importer.mesh3DForName("MissingPositionIndices"); |
||||
CORRADE_VERIFY(id > -1); |
||||
|
||||
std::ostringstream out; |
||||
Error::setOutput(&out); |
||||
CORRADE_VERIFY(!importer.mesh3D(id)); |
||||
CORRADE_COMPARE(out.str(), "Trade::ObjImporter::mesh3D(): incomplete position data\n"); |
||||
} |
||||
|
||||
void ObjImporterTest::missingNormalData() { |
||||
ObjImporter importer; |
||||
CORRADE_VERIFY(importer.openFile(Utility::Directory::join(OBJIMPORTER_TEST_DIR, "missingData.obj"))); |
||||
const Int id = importer.mesh3DForName("MissingNormalData"); |
||||
CORRADE_VERIFY(id > -1); |
||||
|
||||
std::ostringstream out; |
||||
Error::setOutput(&out); |
||||
CORRADE_VERIFY(!importer.mesh3D(id)); |
||||
CORRADE_COMPARE(out.str(), "Trade::ObjImporter::mesh3D(): incomplete normal data\n"); |
||||
} |
||||
|
||||
void ObjImporterTest::missingNormalIndices() { |
||||
ObjImporter importer; |
||||
CORRADE_VERIFY(importer.openFile(Utility::Directory::join(OBJIMPORTER_TEST_DIR, "missingData.obj"))); |
||||
const Int id = importer.mesh3DForName("MissingNormalIndices"); |
||||
CORRADE_VERIFY(id > -1); |
||||
|
||||
std::ostringstream out; |
||||
Error::setOutput(&out); |
||||
CORRADE_VERIFY(!importer.mesh3D(id)); |
||||
CORRADE_COMPARE(out.str(), "Trade::ObjImporter::mesh3D(): incomplete normal data\n"); |
||||
} |
||||
|
||||
void ObjImporterTest::missingTextureCoordinateData() { |
||||
ObjImporter importer; |
||||
CORRADE_VERIFY(importer.openFile(Utility::Directory::join(OBJIMPORTER_TEST_DIR, "missingData.obj"))); |
||||
const Int id = importer.mesh3DForName("MissingTextureData"); |
||||
CORRADE_VERIFY(id > -1); |
||||
|
||||
std::ostringstream out; |
||||
Error::setOutput(&out); |
||||
CORRADE_VERIFY(!importer.mesh3D(id)); |
||||
CORRADE_COMPARE(out.str(), "Trade::ObjImporter::mesh3D(): incomplete texture coordinate data\n"); |
||||
} |
||||
|
||||
void ObjImporterTest::missingTextureCoordinateIndices() { |
||||
ObjImporter importer; |
||||
CORRADE_VERIFY(importer.openFile(Utility::Directory::join(OBJIMPORTER_TEST_DIR, "missingData.obj"))); |
||||
const Int id = importer.mesh3DForName("MissingTextureIndices"); |
||||
CORRADE_VERIFY(id > -1); |
||||
|
||||
std::ostringstream out; |
||||
Error::setOutput(&out); |
||||
CORRADE_VERIFY(!importer.mesh3D(id)); |
||||
CORRADE_COMPARE(out.str(), "Trade::ObjImporter::mesh3D(): incomplete texture coordinate data\n"); |
||||
} |
||||
|
||||
void ObjImporterTest::wrongNormalIndexCount() { |
||||
ObjImporter importer; |
||||
CORRADE_VERIFY(importer.openFile(Utility::Directory::join(OBJIMPORTER_TEST_DIR, "wrongIndexCount.obj"))); |
||||
const Int id = importer.mesh3DForName("ShortNormalIndices"); |
||||
CORRADE_VERIFY(id > -1); |
||||
|
||||
std::ostringstream out; |
||||
Error::setOutput(&out); |
||||
CORRADE_VERIFY(!importer.mesh3D(id)); |
||||
CORRADE_COMPARE(out.str(), "Trade::ObjImporter::mesh3D(): some normal indices are missing\n"); |
||||
} |
||||
|
||||
void ObjImporterTest::wrongTextureCoordinateIndexCount() { |
||||
ObjImporter importer; |
||||
CORRADE_VERIFY(importer.openFile(Utility::Directory::join(OBJIMPORTER_TEST_DIR, "wrongIndexCount.obj"))); |
||||
const Int id = importer.mesh3DForName("ShortTextureIndices"); |
||||
CORRADE_VERIFY(id > -1); |
||||
|
||||
std::ostringstream out; |
||||
Error::setOutput(&out); |
||||
CORRADE_VERIFY(!importer.mesh3D(id)); |
||||
CORRADE_COMPARE(out.str(), "Trade::ObjImporter::mesh3D(): some texture coordinate indices are missing\n"); |
||||
} |
||||
|
||||
void ObjImporterTest::unsupportedKeyword() { |
||||
ObjImporter importer; |
||||
CORRADE_VERIFY(importer.openFile(Utility::Directory::join(OBJIMPORTER_TEST_DIR, "keywords.obj"))); |
||||
const Int id = importer.mesh3DForName("UnsupportedKeyword"); |
||||
CORRADE_VERIFY(id > -1); |
||||
|
||||
/* Everything should be parsed properly */ |
||||
const std::optional<MeshData3D> data = importer.mesh3D(id); |
||||
CORRADE_VERIFY(data); |
||||
CORRADE_COMPARE(data->primitive(), MeshPrimitive::Points); |
||||
CORRADE_COMPARE(data->positionArrayCount(), 1); |
||||
CORRADE_COMPARE(data->positions(0), (std::vector<Vector3>{ |
||||
{0.0f, 1.0f, 2.0f} |
||||
})); |
||||
CORRADE_COMPARE(data->indices(), std::vector<UnsignedInt>{0}); |
||||
} |
||||
|
||||
void ObjImporterTest::unknownKeyword() { |
||||
ObjImporter importer; |
||||
CORRADE_VERIFY(importer.openFile(Utility::Directory::join(OBJIMPORTER_TEST_DIR, "keywords.obj"))); |
||||
const Int id = importer.mesh3DForName("UnknownKeyword"); |
||||
CORRADE_VERIFY(id > -1); |
||||
|
||||
std::ostringstream out; |
||||
Error::setOutput(&out); |
||||
CORRADE_VERIFY(!importer.mesh3D(id)); |
||||
CORRADE_COMPARE(out.str(), "Trade::ObjImporter::mesh3D(): unknown keyword bleh\n"); |
||||
} |
||||
|
||||
}}} |
||||
|
||||
CORRADE_TEST_MAIN(Magnum::Trade::Test::ObjImporterTest) |
||||
@ -0,0 +1,26 @@
|
||||
/* |
||||
This file is part of Magnum. |
||||
|
||||
Copyright © 2010, 2011, 2012, 2013, 2014 |
||||
Vladimír Vondruš <mosra@centrum.cz> |
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a |
||||
copy of this software and associated documentation files (the "Software"), |
||||
to deal in the Software without restriction, including without limitation |
||||
the rights to use, copy, modify, merge, publish, distribute, sublicense, |
||||
and/or sell copies of the Software, and to permit persons to whom the |
||||
Software is furnished to do so, subject to the following conditions: |
||||
|
||||
The above copyright notice and this permission notice shall be included |
||||
in all copies or substantial portions of the Software. |
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
||||
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
||||
DEALINGS IN THE SOFTWARE. |
||||
*/ |
||||
|
||||
#define OBJIMPORTER_TEST_DIR "${CMAKE_CURRENT_SOURCE_DIR}" |
||||
@ -0,0 +1 @@
|
||||
# Nothinng to see here |
||||
@ -0,0 +1,7 @@
|
||||
o UnsupportedKeyword |
||||
g VertexGroup |
||||
v 0 1 2 |
||||
p 1 |
||||
|
||||
o UnknownKeyword |
||||
bleh |
||||
@ -0,0 +1,8 @@
|
||||
# Positions |
||||
v 0.5 2 3 |
||||
v 0 1.5 1 |
||||
v 2 3 5.0 |
||||
|
||||
# Lines |
||||
l 1 2 |
||||
l 2 3 |
||||
@ -0,0 +1,23 @@
|
||||
o MissingPositionData |
||||
p 1 |
||||
|
||||
o MissingPositionIndices |
||||
v 1 2 3 |
||||
|
||||
o MissingNormalData |
||||
v 1 2 3 |
||||
p 1//1 |
||||
|
||||
o MissingNormalIndices |
||||
v 1 2 3 |
||||
vn 1 2 3 |
||||
p 1 |
||||
|
||||
o MissingTextureData |
||||
v 1 2 3 |
||||
p 1/1 |
||||
|
||||
o MissingTextureIndices |
||||
v 1 2 3 |
||||
vt 1 2 |
||||
p 1 |
||||
@ -0,0 +1,13 @@
|
||||
# Positions |
||||
v 0.5 2 3 |
||||
v 0 1.5 1 |
||||
v 2 3 5.0 |
||||
|
||||
# Points |
||||
p 1 |
||||
p 3 |
||||
p 2 |
||||
|
||||
# Lines |
||||
l 1 2 |
||||
l 2 3 |
||||
@ -0,0 +1,21 @@
|
||||
# Points |
||||
o PointMesh |
||||
v 0.5 2 3 |
||||
v 0 1.5 1 |
||||
p 1 |
||||
p 2 |
||||
|
||||
# Lines |
||||
o LineMesh |
||||
v 0.5 2 3 |
||||
v 0 1.5 1 |
||||
l 1 2 |
||||
l 2 1 |
||||
|
||||
# Triangles |
||||
o TriangleMesh |
||||
v 0.5 2 3 |
||||
v 0 1.5 1 |
||||
v 2 3 5.5 |
||||
f 1 2 3 |
||||
f 3 2 1 |
||||
@ -0,0 +1,2 @@
|
||||
# Named mesh |
||||
o MyMesh |
||||
@ -0,0 +1,12 @@
|
||||
# Positions |
||||
v 0.5 2 3 |
||||
v 0 1.5 1 |
||||
|
||||
# Normals (don't have to be normalized) |
||||
vn 1 0.5 3.5 |
||||
vn 0.5 1 0.5 |
||||
|
||||
# Lines |
||||
l 1//1 2//1 |
||||
l 1//2 2//2 |
||||
l 2//1 1//1 |
||||
@ -0,0 +1,17 @@
|
||||
o SupportedPositionW |
||||
v 1.5 2 3 1.0 |
||||
p 1 |
||||
|
||||
o SupportedTextureW |
||||
v 1.5 2 3 |
||||
vt 0.5 0.7 0.0 |
||||
p 1/1 |
||||
|
||||
o UnsupportedPositionW |
||||
v 1.5 2 3 0.8 |
||||
p 1 |
||||
|
||||
o UnsupportedTextureW |
||||
v 1.5 2 3 |
||||
vt 0.5 0.7 0.5 |
||||
p 1/1 |
||||
@ -0,0 +1,10 @@
|
||||
# Positions |
||||
v 0.5 2 3 |
||||
v 0 1.5 1 |
||||
v 2 3 5.0 |
||||
|
||||
# Points |
||||
p 1 |
||||
p 3 |
||||
p 2 |
||||
p 1 |
||||
@ -0,0 +1,12 @@
|
||||
# Positions |
||||
v 0.5 2 3 |
||||
v 0 1.5 1 |
||||
|
||||
# Texture coordinates |
||||
vt 1 0.5 |
||||
vt 0.5 1 |
||||
|
||||
# Lines |
||||
l 1/1 2/1 |
||||
l 1/2 2/2 |
||||
l 2/1 1/1 |
||||
@ -0,0 +1,17 @@
|
||||
# Positions |
||||
v 0.5 2 3 |
||||
v 0 1.5 1 |
||||
|
||||
# Texture coordinates |
||||
vt 1 0.5 |
||||
vt 0.5 1 |
||||
|
||||
# Normals |
||||
vn 1 0.5 3.5 |
||||
vn 0.5 1 0.5 |
||||
|
||||
# Lines |
||||
l 1/1/1 2/1/2 |
||||
l 1/2/2 2/2/1 |
||||
l 2/1/2 1/1/1 |
||||
l 2/2/2 1/2/2 |
||||
@ -0,0 +1,9 @@
|
||||
# Positions |
||||
v 0.5 2 3 |
||||
v 0 1.5 1 |
||||
v 2 3 5.0 |
||||
v 2.5 0 1 |
||||
|
||||
# Triangles |
||||
f 1 2 3 |
||||
f 4 2 1 |
||||
@ -0,0 +1,2 @@
|
||||
v 1 2 3 |
||||
o SecondMesh |
||||
@ -0,0 +1,13 @@
|
||||
o ShortNormalIndices |
||||
v 1 2 3 |
||||
vn 1 2 3 |
||||
p 1//1 |
||||
p 1 |
||||
p 1//1 |
||||
|
||||
o ShortTextureIndices |
||||
v 1 2 3 |
||||
vt 1 2 |
||||
p 1/1 |
||||
p 1 |
||||
p 1/1 |
||||
@ -0,0 +1,29 @@
|
||||
o ShortFloat |
||||
v 0.5 1.0 |
||||
|
||||
o LongFloat |
||||
v 0.5 1 2 |
||||
vn 0.5 1.0 2.3 7.4 |
||||
|
||||
o LongOptionalFloat |
||||
v 0.5 1 2 0.0 3.5 |
||||
|
||||
o InvalidIndices |
||||
v 1 2 3 |
||||
p 1/1/1/1 |
||||
|
||||
o WrongPointIndices |
||||
v 1 2 3 |
||||
p 1 1 |
||||
|
||||
o WrongLineIndices |
||||
v 1 2 3 |
||||
l 1 |
||||
|
||||
o WrongTriangleIndices |
||||
v 1 2 3 |
||||
f 1 1 |
||||
|
||||
o PolygonIndices |
||||
v 1 2 3 |
||||
f 1 1 1 1 |
||||
@ -0,0 +1,20 @@
|
||||
o WrongFloat |
||||
v 1 bleh 2 |
||||
p 1 |
||||
|
||||
o WrongInteger |
||||
v 1 0 2 |
||||
p bleh |
||||
|
||||
o PositionIndexOutOfRange |
||||
v 1 0 2 |
||||
p 2 |
||||
|
||||
o TextureIndexOutOfRange |
||||
v 1 0 2 |
||||
vt 0 1 |
||||
p 1/2 |
||||
|
||||
o ZeroIndex |
||||
v 1 0 2 |
||||
p 0 |
||||
@ -0,0 +1,29 @@
|
||||
/*
|
||||
This file is part of Magnum. |
||||
|
||||
Copyright © 2010, 2011, 2012, 2013, 2014 |
||||
Vladimír Vondruš <mosra@centrum.cz> |
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a |
||||
copy of this software and associated documentation files (the "Software"), |
||||
to deal in the Software without restriction, including without limitation |
||||
the rights to use, copy, modify, merge, publish, distribute, sublicense, |
||||
and/or sell copies of the Software, and to permit persons to whom the |
||||
Software is furnished to do so, subject to the following conditions: |
||||
|
||||
The above copyright notice and this permission notice shall be included |
||||
in all copies or substantial portions of the Software. |
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
||||
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
||||
DEALINGS IN THE SOFTWARE. |
||||
*/ |
||||
|
||||
#include "MagnumPlugins/ObjImporter/ObjImporter.h" |
||||
|
||||
CORRADE_PLUGIN_REGISTER(ObjImporter, Magnum::Trade::ObjImporter, |
||||
"cz.mosra.magnum.Trade.AbstractImporter/0.3") |
||||
Loading…
Reference in new issue