update assimp

This commit is contained in:
Garux 2021-04-07 01:56:00 +03:00
parent b1043424ed
commit 31a79faee4
23 changed files with 285 additions and 182 deletions

View File

@ -454,7 +454,7 @@ IF(ASSIMP_HUNTER_ENABLED)
ELSE() ELSE()
# If the zlib is already found outside, add an export in case assimpTargets can't find it. # If the zlib is already found outside, add an export in case assimpTargets can't find it.
IF( ZLIB_FOUND ) IF( ZLIB_FOUND )
INSTALL( TARGETS zlib INSTALL( TARGETS zlib zlibstatic
EXPORT "${TARGETS_EXPORT_NAME}") EXPORT "${TARGETS_EXPORT_NAME}")
ENDIF() ENDIF()

View File

@ -1,6 +1,6 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
Copyright (c) 2006-2020, assimp team Copyright (c) 2006-2021, assimp team
All rights reserved. All rights reserved.
Redistribution and use of this software in source and binary forms, Redistribution and use of this software in source and binary forms,

View File

@ -76,9 +76,6 @@ For more information, visit [our website](http://assimp.org/). Or check out the
If the docs don't solve your problem, ask on [StackOverflow with the assimp-tag](http://stackoverflow.com/questions/tagged/assimp?sort=newest). If you think you found a bug, please open an issue on Github. If the docs don't solve your problem, ask on [StackOverflow with the assimp-tag](http://stackoverflow.com/questions/tagged/assimp?sort=newest). If you think you found a bug, please open an issue on Github.
For development discussions, there is also a (very low-volume) mailing list, _assimp-discussions_
[(subscribe here)]( https://lists.sourceforge.net/lists/listinfo/assimp-discussions)
Open Asset Import Library is a library to load various 3d file formats into a shared, in-memory format. It supports more than __40 file formats__ for import and a growing selection of file formats for export. Open Asset Import Library is a library to load various 3d file formats into a shared, in-memory format. It supports more than __40 file formats__ for import and a growing selection of file formats for export.
And we also have a Gitter-channel:Gitter [![Join the chat at https://gitter.im/assimp/assimp](https://badges.gitter.im/assimp/assimp.svg)](https://gitter.im/assimp/assimp?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)<br> And we also have a Gitter-channel:Gitter [![Join the chat at https://gitter.im/assimp/assimp](https://badges.gitter.im/assimp/assimp.svg)](https://gitter.im/assimp/assimp?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)<br>
@ -103,9 +100,6 @@ Become a financial contributor and help us sustain our community. [[Contribute](
<a href="https://opencollective.com/assimp"><img src="https://opencollective.com/assimp/individuals.svg?width=890"></a> <a href="https://opencollective.com/assimp"><img src="https://opencollective.com/assimp/individuals.svg?width=890"></a>
Monthly donations via Patreon:
<br>[![Patreon](https://cloud.githubusercontent.com/assets/8225057/5990484/70413560-a9ab-11e4-8942-1a63607c0b00.png)](http://www.patreon.com/assimp)
#### Organizations #### Organizations

View File

@ -981,9 +981,9 @@ void Discreet3DSImporter::ParseMeshChunk() {
mMesh.mMat.a3 = stream->GetF4(); mMesh.mMat.a3 = stream->GetF4();
mMesh.mMat.b3 = stream->GetF4(); mMesh.mMat.b3 = stream->GetF4();
mMesh.mMat.c3 = stream->GetF4(); mMesh.mMat.c3 = stream->GetF4();
mMesh.mMat.a4 = stream->GetF4(); mMesh.mMat.d1 = stream->GetF4();
mMesh.mMat.b4 = stream->GetF4(); mMesh.mMat.d2 = stream->GetF4();
mMesh.mMat.c4 = stream->GetF4(); mMesh.mMat.d3 = stream->GetF4();
} break; } break;
case Discreet3DS::CHUNK_MAPLIST: { case Discreet3DS::CHUNK_MAPLIST: {

View File

@ -39,16 +39,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
*/ */
/// \file AMFImporter.cpp
/// \brief AMF-format files importer for Assimp: main algorithm implementation.
/// \date 2016
/// \author smal.root@gmail.com
#ifndef ASSIMP_BUILD_NO_AMF_IMPORTER #ifndef ASSIMP_BUILD_NO_AMF_IMPORTER
// Header files, Assimp. // Header files, Assimp.
#include "AMFImporter.hpp" #include "AMFImporter.hpp"
#include "AMFImporter_Macro.hpp"
#include <assimp/DefaultIOSystem.h> #include <assimp/DefaultIOSystem.h>
#include <assimp/fast_atof.h> #include <assimp/fast_atof.h>
@ -307,14 +301,14 @@ void AMFImporter::ParseNode_Root() {
throw DeadlyImportError("Root node \"amf\" not found."); throw DeadlyImportError("Root node \"amf\" not found.");
} }
XmlNode node = *root; XmlNode node = *root;
mUnit = ai_str_tolower(std::string(node.attribute("unit").as_string())); mUnit = ai_tolower(std::string(node.attribute("unit").as_string()));
mVersion = node.attribute("version").as_string(); mVersion = node.attribute("version").as_string();
// Read attributes for node <amf>. // Read attributes for node <amf>.
// Check attributes // Check attributes
if (!mUnit.empty()) { if (!mUnit.empty()) {
if ((mUnit != "inch") && (mUnit != "millimeter") && (mUnit != "meter") && (mUnit != "feet") && (mUnit != "micron")) { if ((mUnit != "inch") && (mUnit != "millimeters") && (mUnit != "millimeter") && (mUnit != "meter") && (mUnit != "feet") && (mUnit != "micron")) {
Throw_IncorrectAttrValue("unit", mUnit); Throw_IncorrectAttrValue("unit", mUnit);
} }
} }
@ -409,20 +403,20 @@ void AMFImporter::ParseNode_Instance(XmlNode &node) {
if (!node.empty()) { if (!node.empty()) {
ParseHelper_Node_Enter(ne); ParseHelper_Node_Enter(ne);
for (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling()) { for (auto &currentNode : node.children()) {
const std::string &currentName = currentNode.name(); const std::string &currentName = currentNode.name();
if (currentName == "deltax") { if (currentName == "deltax") {
als.Delta.x = (ai_real)std::atof(currentNode.value()); XmlParser::getValueAsFloat(currentNode, als.Delta.x);
} else if (currentName == "deltay") { } else if (currentName == "deltay") {
als.Delta.y = (ai_real)std::atof(currentNode.value()); XmlParser::getValueAsFloat(currentNode, als.Delta.y);
} else if (currentName == "deltaz") { } else if (currentName == "deltaz") {
als.Delta.z = (ai_real)std::atof(currentNode.value()); XmlParser::getValueAsFloat(currentNode, als.Delta.z);
} else if (currentName == "rx") { } else if (currentName == "rx") {
als.Delta.x = (ai_real)std::atof(currentNode.value()); XmlParser::getValueAsFloat(currentNode, als.Delta.x);
} else if (currentName == "ry") { } else if (currentName == "ry") {
als.Delta.y = (ai_real)std::atof(currentNode.value()); XmlParser::getValueAsFloat(currentNode, als.Delta.y);
} else if (currentName == "rz") { } else if (currentName == "rz") {
als.Delta.z = (ai_real)std::atof(currentNode.value()); XmlParser::getValueAsFloat(currentNode, als.Delta.z);
} }
} }
ParseHelper_Node_Exit(); ParseHelper_Node_Exit();
@ -458,7 +452,7 @@ void AMFImporter::ParseNode_Object(XmlNode &node) {
// Check for child nodes // Check for child nodes
if (!node.empty()) { if (!node.empty()) {
ParseHelper_Node_Enter(ne); ParseHelper_Node_Enter(ne);
for (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling()) { for (auto &currentNode : node.children()) {
const std::string &currentName = currentNode.name(); const std::string &currentName = currentNode.name();
if (currentName == "color") { if (currentName == "color") {
ParseNode_Color(currentNode); ParseNode_Color(currentNode);

View File

@ -39,16 +39,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
*/ */
/// \file AMFImporter_Geometry.cpp
/// \brief Parsing data from geometry nodes.
/// \date 2016
/// \author smal.root@gmail.com
#ifndef ASSIMP_BUILD_NO_AMF_IMPORTER #ifndef ASSIMP_BUILD_NO_AMF_IMPORTER
#include "AMFImporter.hpp" #include "AMFImporter.hpp"
#include "AMFImporter_Macro.hpp"
#include <assimp/ParsingUtils.h> #include <assimp/ParsingUtils.h>
namespace Assimp { namespace Assimp {
@ -103,18 +96,18 @@ void AMFImporter::ParseNode_Vertices(XmlNode &node) {
// create new mesh object. // create new mesh object.
ne = new AMFVertices(mNodeElement_Cur); ne = new AMFVertices(mNodeElement_Cur);
// Check for child nodes // Check for child nodes
pugi::xml_node vertexNode = node.child("vertex"); if (node.empty()) {
if (!vertexNode.empty()) {
ParseHelper_Node_Enter(ne);
ParseNode_Vertex(vertexNode);
ParseHelper_Node_Exit();
} else {
mNodeElement_Cur->Child.push_back(ne); // Add element to child list of current element mNodeElement_Cur->Child.push_back(ne); // Add element to child list of current element
} // if(!mReader->isEmptyElement()) else return;
}
ParseHelper_Node_Enter(ne);
for (XmlNode &currentNode : node.children()) {
const std::string &currentName = currentNode.name();
if (currentName == "vertex") {
ParseNode_Vertex(currentNode);
}
}
ParseHelper_Node_Exit();
mNodeElement_List.push_back(ne); // and to node element list because its a new object in graph. mNodeElement_List.push_back(ne); // and to node element list because its a new object in graph.
} }
@ -166,27 +159,25 @@ void AMFImporter::ParseNode_Vertex(XmlNode &node) {
// X, Y, or Z coordinate, respectively, of a vertex position in space. // X, Y, or Z coordinate, respectively, of a vertex position in space.
void AMFImporter::ParseNode_Coordinates(XmlNode &node) { void AMFImporter::ParseNode_Coordinates(XmlNode &node) {
AMFNodeElementBase *ne = nullptr; AMFNodeElementBase *ne = nullptr;
// create new color object.
ne = new AMFCoordinates(mNodeElement_Cur);
AMFCoordinates &als = *((AMFCoordinates *)ne); // alias for convenience
if (!node.empty()) { if (!node.empty()) {
ne = new AMFCoordinates(mNodeElement_Cur);
ParseHelper_Node_Enter(ne); ParseHelper_Node_Enter(ne);
for (XmlNode &currentNode : node.children()) { for (XmlNode &currentNode : node.children()) {
const std::string &currentName = currentNode.name(); // create new color object.
if (currentName == "X") { AMFCoordinates &als = *((AMFCoordinates *)ne); // alias for convenience
const std::string &currentName = ai_tolower(currentNode.name());
if (currentName == "x") {
XmlParser::getValueAsFloat(currentNode, als.Coordinate.x); XmlParser::getValueAsFloat(currentNode, als.Coordinate.x);
} else if (currentName == "Y") { } else if (currentName == "y") {
XmlParser::getValueAsFloat(currentNode, als.Coordinate.y); XmlParser::getValueAsFloat(currentNode, als.Coordinate.y);
} else if (currentName == "Z") { } else if (currentName == "z") {
XmlParser::getValueAsFloat(currentNode, als.Coordinate.z); XmlParser::getValueAsFloat(currentNode, als.Coordinate.z);
} }
} }
ParseHelper_Node_Exit(); ParseHelper_Node_Exit();
} else { } else {
mNodeElement_Cur->Child.push_back(ne); mNodeElement_Cur->Child.push_back(new AMFCoordinates(mNodeElement_Cur));
} }
mNodeElement_List.push_back(ne); // and to node element list because its a new object in graph. mNodeElement_List.push_back(ne); // and to node element list because its a new object in graph.
@ -216,7 +207,7 @@ void AMFImporter::ParseNode_Volume(XmlNode &node) {
bool col_read = false; bool col_read = false;
if (!node.empty()) { if (!node.empty()) {
ParseHelper_Node_Enter(ne); ParseHelper_Node_Enter(ne);
for (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling()) { for (auto &currentNode : node.children()) {
const std::string currentName = currentNode.name(); const std::string currentName = currentNode.name();
if (currentName == "color") { if (currentName == "color") {
if (col_read) Throw_MoreThanOnceDefined(currentName, "color", "Only one color can be defined for <volume>."); if (col_read) Throw_MoreThanOnceDefined(currentName, "color", "Only one color can be defined for <volume>.");
@ -258,7 +249,8 @@ void AMFImporter::ParseNode_Triangle(XmlNode &node) {
bool col_read = false; bool col_read = false;
if (!node.empty()) { if (!node.empty()) {
ParseHelper_Node_Enter(ne); ParseHelper_Node_Enter(ne);
for (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling()) { std::string v;
for (auto &currentNode : node.children()) {
const std::string currentName = currentNode.name(); const std::string currentName = currentNode.name();
if (currentName == "color") { if (currentName == "color") {
if (col_read) Throw_MoreThanOnceDefined(currentName, "color", "Only one color can be defined for <triangle>."); if (col_read) Throw_MoreThanOnceDefined(currentName, "color", "Only one color can be defined for <triangle>.");
@ -269,11 +261,14 @@ void AMFImporter::ParseNode_Triangle(XmlNode &node) {
} else if (currentName == "map") { } else if (currentName == "map") {
ParseNode_TexMap(currentNode, true); ParseNode_TexMap(currentNode, true);
} else if (currentName == "v1") { } else if (currentName == "v1") {
als.V[0] = std::atoi(currentNode.value()); XmlParser::getValueAsString(currentNode, v);
als.V[0] = std::atoi(v.c_str());
} else if (currentName == "v2") { } else if (currentName == "v2") {
als.V[1] = std::atoi(currentNode.value()); XmlParser::getValueAsString(currentNode, v);
als.V[1] = std::atoi(v.c_str());
} else if (currentName == "v3") { } else if (currentName == "v3") {
als.V[2] = std::atoi(currentNode.value()); XmlParser::getValueAsString(currentNode, v);
als.V[2] = std::atoi(v.c_str());
} }
} }
ParseHelper_Node_Exit(); ParseHelper_Node_Exit();

View File

@ -65,18 +65,20 @@ namespace Assimp {
// Red, Greed, Blue and Alpha (transparency) component of a color in sRGB space, values ranging from 0 to 1. The // Red, Greed, Blue and Alpha (transparency) component of a color in sRGB space, values ranging from 0 to 1. The
// values can be specified as constants, or as a formula depending on the coordinates. // values can be specified as constants, or as a formula depending on the coordinates.
void AMFImporter::ParseNode_Color(XmlNode &node) { void AMFImporter::ParseNode_Color(XmlNode &node) {
std::string profile = node.attribute("profile").as_string(); if (node.empty()) {
return;
}
// create new color object. const std::string &profile = node.attribute("profile").as_string();
AMFNodeElementBase *ne = new AMFColor(mNodeElement_Cur);
AMFColor& als = *((AMFColor*)ne);// alias for convenience
als.Profile = profile;
if (!node.empty()) {
ParseHelper_Node_Enter(ne);
bool read_flag[4] = { false, false, false, false }; bool read_flag[4] = { false, false, false, false };
AMFNodeElementBase *ne = new AMFColor(mNodeElement_Cur);
AMFColor &als = *((AMFColor *)ne); // alias for convenience
ParseHelper_Node_Enter(ne);
for (pugi::xml_node &child : node.children()) { for (pugi::xml_node &child : node.children()) {
std::string name = child.name(); // create new color object.
als.Profile = profile;
const std::string &name = child.name();
if ( name == "r") { if ( name == "r") {
read_flag[0] = true; read_flag[0] = true;
XmlParser::getValueAsFloat(child, als.Color.r); XmlParser::getValueAsFloat(child, als.Color.r);
@ -90,23 +92,18 @@ void AMFImporter::ParseNode_Color(XmlNode &node) {
read_flag[3] = true; read_flag[3] = true;
XmlParser::getValueAsFloat(child, als.Color.a); XmlParser::getValueAsFloat(child, als.Color.a);
} }
ParseHelper_Node_Exit();
}
// check that all components was defined
if (!(read_flag[0] && read_flag[1] && read_flag[2])) {
throw DeadlyImportError("Not all color components are defined.");
}
// check if <a> is absent. Then manually add "a == 1". // check if <a> is absent. Then manually add "a == 1".
if (!read_flag[3]) { if (!read_flag[3]) {
als.Color.a = 1; als.Color.a = 1;
} }
} else {
mNodeElement_Cur->Child.push_back(ne);// Add element to child list of current element
} }
als.Composed = false; als.Composed = false;
mNodeElement_List.push_back(ne);// and to node element list because its a new object in graph. mNodeElement_List.push_back(ne); // and to node element list because its a new object in graph.
ParseHelper_Node_Exit();
// check that all components was defined
if (!(read_flag[0] && read_flag[1] && read_flag[2])) {
throw DeadlyImportError("Not all color components are defined.");
}
} }
// <material // <material
@ -158,11 +155,11 @@ void AMFImporter::ParseNode_Material(XmlNode &node) {
// Multi elements - Yes. // Multi elements - Yes.
// Parent element - <amf>. // Parent element - <amf>.
void AMFImporter::ParseNode_Texture(XmlNode &node) { void AMFImporter::ParseNode_Texture(XmlNode &node) {
std::string id = node.attribute("id").as_string(); const std::string id = node.attribute("id").as_string();
uint32_t width = node.attribute("width").as_uint(); const uint32_t width = node.attribute("width").as_uint();
uint32_t height = node.attribute("height").as_uint(); const uint32_t height = node.attribute("height").as_uint();
uint32_t depth = node.attribute("depth").as_uint(); uint32_t depth = node.attribute("depth").as_uint();
std::string type = node.attribute("type").as_string(); const std::string type = node.attribute("type").as_string();
bool tiled = node.attribute("tiled").as_bool(); bool tiled = node.attribute("tiled").as_bool();
if (node.empty()) { if (node.empty()) {
@ -174,7 +171,8 @@ void AMFImporter::ParseNode_Texture(XmlNode &node) {
AMFTexture& als = *((AMFTexture*)ne);// alias for convenience AMFTexture& als = *((AMFTexture*)ne);// alias for convenience
std::string enc64_data = node.value(); std::string enc64_data;
XmlParser::getValueAsString(node, enc64_data);
// Check for child nodes // Check for child nodes
// check that all components was defined // check that all components was defined
@ -182,14 +180,11 @@ void AMFImporter::ParseNode_Texture(XmlNode &node) {
throw DeadlyImportError("ID for texture must be defined."); throw DeadlyImportError("ID for texture must be defined.");
} }
if (width < 1) { if (width < 1) {
throw DeadlyImportError("INvalid width for texture."); throw DeadlyImportError("Invalid width for texture.");
} }
if (height < 1) { if (height < 1) {
throw DeadlyImportError("Invalid height for texture."); throw DeadlyImportError("Invalid height for texture.");
} }
if (depth < 1) {
throw DeadlyImportError("Invalid depth for texture.");
}
if (type != "grayscale") { if (type != "grayscale") {
throw DeadlyImportError("Invalid type for texture."); throw DeadlyImportError("Invalid type for texture.");
} }
@ -203,7 +198,9 @@ void AMFImporter::ParseNode_Texture(XmlNode &node) {
als.Depth = depth; als.Depth = depth;
als.Tiled = tiled; als.Tiled = tiled;
ParseHelper_Decode_Base64(enc64_data, als.Data); ParseHelper_Decode_Base64(enc64_data, als.Data);
if (depth == 0) {
depth = (uint32_t)(als.Data.size() / (width * height));
}
// check data size // check data size
if ((width * height * depth) != als.Data.size()) { if ((width * height * depth) != als.Data.size()) {
throw DeadlyImportError("Texture has incorrect data size."); throw DeadlyImportError("Texture has incorrect data size.");
@ -233,20 +230,18 @@ void AMFImporter::ParseNode_TexMap(XmlNode &node, const bool pUseOldName) {
AMFTexMap &als = *((AMFTexMap *)ne); // AMFTexMap &als = *((AMFTexMap *)ne); //
std::string rtexid, gtexid, btexid, atexid; std::string rtexid, gtexid, btexid, atexid;
if (!node.empty()) { if (!node.empty()) {
ParseHelper_Node_Enter(ne); for (pugi::xml_attribute &attr : node.attributes()) {
for (XmlNode &currentNode : node.children()) { const std::string &currentAttr = attr.name();
const std::string &currentName = currentNode.name(); if (currentAttr == "rtexid") {
if (currentName == "rtexid") { rtexid = attr.as_string();
XmlParser::getValueAsString(node, rtexid); } else if (currentAttr == "gtexid") {
} else if (currentName == "gtexid") { gtexid = attr.as_string();
XmlParser::getValueAsString(node, gtexid); } else if (currentAttr == "btexid") {
} else if (currentName == "btexid") { btexid = attr.as_string();
XmlParser::getValueAsString(node, btexid); } else if (currentAttr == "atexid") {
} else if (currentName == "atexid") { atexid = attr.as_string();
XmlParser::getValueAsString(node, atexid);
} }
} }
ParseHelper_Node_Exit();
} }
// create new texture coordinates object, alias for convenience // create new texture coordinates object, alias for convenience
@ -256,7 +251,6 @@ void AMFImporter::ParseNode_TexMap(XmlNode &node, const bool pUseOldName) {
} }
// Check for children nodes // Check for children nodes
//XML_CheckNode_MustHaveChildren();
if (node.children().begin() == node.children().end()) { if (node.children().begin() == node.children().end()) {
throw DeadlyImportError("Invalid children definition."); throw DeadlyImportError("Invalid children definition.");
} }
@ -264,28 +258,31 @@ void AMFImporter::ParseNode_TexMap(XmlNode &node, const bool pUseOldName) {
bool read_flag[6] = { false, false, false, false, false, false }; bool read_flag[6] = { false, false, false, false, false, false };
if (!pUseOldName) { if (!pUseOldName) {
for (pugi::xml_attribute &attr : node.attributes()) { ParseHelper_Node_Enter(ne);
const std::string name = attr.name(); for ( XmlNode &currentNode : node.children()) {
const std::string &name = currentNode.name();
if (name == "utex1") { if (name == "utex1") {
read_flag[0] = true; read_flag[0] = true;
als.TextureCoordinate[0].x = attr.as_float(); XmlParser::getValueAsFloat(node, als.TextureCoordinate[0].x);
} else if (name == "utex2") { } else if (name == "utex2") {
read_flag[1] = true; read_flag[1] = true;
als.TextureCoordinate[1].x = attr.as_float(); XmlParser::getValueAsFloat(node, als.TextureCoordinate[1].x);
} else if (name == "utex3") { } else if (name == "utex3") {
read_flag[2] = true; read_flag[2] = true;
als.TextureCoordinate[2].x = attr.as_float(); XmlParser::getValueAsFloat(node, als.TextureCoordinate[2].x);
} else if (name == "vtex1") { } else if (name == "vtex1") {
read_flag[3] = true; read_flag[3] = true;
als.TextureCoordinate[0].y = attr.as_float(); XmlParser::getValueAsFloat(node, als.TextureCoordinate[0].y);
} else if (name == "vtex2") { } else if (name == "vtex2") {
read_flag[4] = true; read_flag[4] = true;
als.TextureCoordinate[1].y = attr.as_float(); XmlParser::getValueAsFloat(node, als.TextureCoordinate[1].y);
} else if (name == "vtex3") { } else if (name == "vtex3") {
read_flag[5] = true; read_flag[5] = true;
als.TextureCoordinate[0].y = attr.as_float(); XmlParser::getValueAsFloat(node, als.TextureCoordinate[2].y);
} }
} }
ParseHelper_Node_Exit();
} else { } else {
for (pugi::xml_attribute &attr : node.attributes()) { for (pugi::xml_attribute &attr : node.attributes()) {
const std::string name = attr.name(); const std::string name = attr.name();

View File

@ -62,12 +62,14 @@ aiColor4D AMFImporter::SPP_Material::GetColor(const float /*pX*/, const float /*
// Check if stored data are supported. // Check if stored data are supported.
if (!Composition.empty()) { if (!Composition.empty()) {
throw DeadlyImportError("IME. GetColor for composition"); throw DeadlyImportError("IME. GetColor for composition");
} else if (Color->Composed) {
throw DeadlyImportError("IME. GetColor, composed color");
} else {
tcol = Color->Color;
} }
if (Color->Composed) {
throw DeadlyImportError("IME. GetColor, composed color");
}
tcol = Color->Color;
// Check if default color must be used // Check if default color must be used
if ((tcol.r == 0) && (tcol.g == 0) && (tcol.b == 0) && (tcol.a == 0)) { if ((tcol.r == 0) && (tcol.g == 0) && (tcol.b == 0) && (tcol.a == 0)) {
tcol.r = 0.5f; tcol.r = 0.5f;
@ -79,13 +81,13 @@ aiColor4D AMFImporter::SPP_Material::GetColor(const float /*pX*/, const float /*
return tcol; return tcol;
} }
void AMFImporter::PostprocessHelper_CreateMeshDataArray(const AMFMesh &pNodeElement, std::vector<aiVector3D> &pVertexCoordinateArray, void AMFImporter::PostprocessHelper_CreateMeshDataArray(const AMFMesh &nodeElement, std::vector<aiVector3D> &vertexCoordinateArray,
std::vector<AMFColor *> &pVertexColorArray) const { std::vector<AMFColor *> &pVertexColorArray) const {
AMFVertices *vn = nullptr; AMFVertices *vn = nullptr;
size_t col_idx; size_t col_idx;
// All data stored in "vertices", search for it. // All data stored in "vertices", search for it.
for (AMFNodeElementBase *ne_child : pNodeElement.Child) { for (AMFNodeElementBase *ne_child : nodeElement.Child) {
if (ne_child->Type == AMFNodeElementBase::ENET_Vertices) { if (ne_child->Type == AMFNodeElementBase::ENET_Vertices) {
vn = (AMFVertices*)ne_child; vn = (AMFVertices*)ne_child;
} }
@ -97,7 +99,7 @@ void AMFImporter::PostprocessHelper_CreateMeshDataArray(const AMFMesh &pNodeElem
} }
// all coordinates stored as child and we need to reserve space for future push_back's. // all coordinates stored as child and we need to reserve space for future push_back's.
pVertexCoordinateArray.reserve(vn->Child.size()); vertexCoordinateArray.reserve(vn->Child.size());
// colors count equal vertices count. // colors count equal vertices count.
pVertexColorArray.resize(vn->Child.size()); pVertexColorArray.resize(vn->Child.size());
@ -112,7 +114,7 @@ void AMFImporter::PostprocessHelper_CreateMeshDataArray(const AMFMesh &pNodeElem
for (AMFNodeElementBase *vtx : vn_child->Child) { for (AMFNodeElementBase *vtx : vn_child->Child) {
if (vtx->Type == AMFNodeElementBase::ENET_Coordinates) { if (vtx->Type == AMFNodeElementBase::ENET_Coordinates) {
pVertexCoordinateArray.push_back(((AMFCoordinates *)vtx)->Coordinate); vertexCoordinateArray.push_back(((AMFCoordinates *)vtx)->Coordinate);
continue; continue;
} }

View File

@ -812,6 +812,18 @@ void FBXExporter::WriteDefinitions ()
// Geometry / FbxMesh // Geometry / FbxMesh
// <~~ aiMesh // <~~ aiMesh
count = mScene->mNumMeshes; count = mScene->mNumMeshes;
// Blendshapes are considered Geometry
int32_t bsDeformerCount=0;
for (size_t mi = 0; mi < mScene->mNumMeshes; ++mi) {
aiMesh* m = mScene->mMeshes[mi];
if (m->mNumAnimMeshes > 0) {
count+=m->mNumAnimMeshes;
bsDeformerCount+=m->mNumAnimMeshes; // One deformer per blendshape
bsDeformerCount++; // Plus one master blendshape deformer
}
}
if (count) { if (count) {
n = FBX::Node("ObjectType", "Geometry"); n = FBX::Node("ObjectType", "Geometry");
n.AddChild("Count", count); n.AddChild("Count", count);
@ -978,7 +990,7 @@ void FBXExporter::WriteDefinitions ()
} }
// Deformer // Deformer
count = int32_t(count_deformers(mScene)); count = int32_t(count_deformers(mScene))+bsDeformerCount;
if (count) { if (count) {
n = FBX::Node("ObjectType", "Deformer"); n = FBX::Node("ObjectType", "Deformer");
n.AddChild("Count", count); n.AddChild("Count", count);
@ -1363,6 +1375,7 @@ void FBXExporter::WriteObjects ()
n.End(outstream, binary, indent, true); n.End(outstream, binary, indent, true);
} }
// aiMaterial // aiMaterial
material_uids.clear(); material_uids.clear();
for (size_t i = 0; i < mScene->mNumMaterials; ++i) { for (size_t i = 0; i < mScene->mNumMaterials; ++i) {
@ -1697,6 +1710,100 @@ void FBXExporter::WriteObjects ()
} }
} }
// Blendshapes, if any
for (size_t mi = 0; mi < mScene->mNumMeshes; ++mi) {
const aiMesh* m = mScene->mMeshes[mi];
if (m->mNumAnimMeshes == 0) {
continue;
}
// make a deformer for this mesh
int64_t deformer_uid = generate_uid();
FBX::Node dnode("Deformer");
dnode.AddProperties(deformer_uid, m->mName.data + FBX::SEPARATOR + "Blendshapes", "BlendShape");
dnode.AddChild("Version", int32_t(101));
dnode.Dump(outstream, binary, indent);
// connect it
connections.emplace_back("C", "OO", deformer_uid, mesh_uids[mi]);
std::vector<int32_t> vertex_indices = vVertexIndice[mi];
for (unsigned int am = 0; am < m->mNumAnimMeshes; ++am) {
aiAnimMesh *pAnimMesh = m->mAnimMeshes[am];
std::string blendshape_name = pAnimMesh->mName.data;
// start the node record
FBX::Node bsnode("Geometry");
int64_t blendshape_uid = generate_uid();
mesh_uids.push_back(blendshape_uid);
bsnode.AddProperty(blendshape_uid);
bsnode.AddProperty(blendshape_name + FBX::SEPARATOR + "Blendshape");
bsnode.AddProperty("Shape");
bsnode.AddChild("Version", int32_t(100));
bsnode.Begin(outstream, binary, indent);
bsnode.DumpProperties(outstream, binary, indent);
bsnode.EndProperties(outstream, binary, indent);
bsnode.BeginChildren(outstream, binary, indent);
indent++;
if (pAnimMesh->HasPositions()) {
std::vector<int32_t>shape_indices;
std::vector<double>pPositionDiff;
std::vector<double>pNormalDiff;
for (unsigned int vt = 0; vt < vertex_indices.size(); ++vt) {
aiVector3D pDiff = (pAnimMesh->mVertices[vertex_indices[vt]] - m->mVertices[vertex_indices[vt]]);
if(pDiff.Length()>1e-8){
shape_indices.push_back(vertex_indices[vt]);
pPositionDiff.push_back(pDiff[0]);
pPositionDiff.push_back(pDiff[1]);
pPositionDiff.push_back(pDiff[2]);
if (pAnimMesh->HasNormals()) {
aiVector3D nDiff = (pAnimMesh->mNormals[vertex_indices[vt]] - m->mNormals[vertex_indices[vt]]);
pNormalDiff.push_back(nDiff[0]);
pNormalDiff.push_back(nDiff[1]);
pNormalDiff.push_back(nDiff[2]);
}
}
}
FBX::Node::WritePropertyNode(
"Indexes", shape_indices, outstream, binary, indent
);
FBX::Node::WritePropertyNode(
"Vertices", pPositionDiff, outstream, binary, indent
);
if (pNormalDiff.size()>0) {
FBX::Node::WritePropertyNode(
"Normals", pNormalDiff, outstream, binary, indent
);
}
}
indent--;
bsnode.End(outstream, binary, indent, true);
// Add blendshape Channel Deformer
FBX::Node sdnode("Deformer");
const int64_t blendchannel_uid = generate_uid();
sdnode.AddProperties(
blendchannel_uid, blendshape_name + FBX::SEPARATOR + "SubDeformer", "BlendShapeChannel"
);
sdnode.AddChild("Version", int32_t(100));
sdnode.AddChild("DeformPercent", int32_t(100));
FBX::Node p("Properties70");
p.AddP70numberA("DeformPercent", 100.);
sdnode.AddChild(p);
// TODO: Normally just one weight per channel, adding stub for later development
std::vector<float>fFullWeights;
fFullWeights.push_back(0.);
sdnode.AddChild("FullWeights", fFullWeights);
sdnode.Dump(outstream, binary, indent);
connections.emplace_back("C", "OO", blendchannel_uid, deformer_uid);
connections.emplace_back("C", "OO", blendshape_uid, blendchannel_uid);
}
}
// bones. // bones.
// //
// output structure: // output structure:

View File

@ -158,6 +158,9 @@ void HMPImporter::InternReadFile(const std::string &pFile,
szBuffer[3] = ((char *)&iMagic)[3]; szBuffer[3] = ((char *)&iMagic)[3];
szBuffer[4] = '\0'; szBuffer[4] = '\0';
delete[] mBuffer;
mBuffer = nullptr;
// We're definitely unable to load this file // We're definitely unable to load this file
throw DeadlyImportError("Unknown HMP subformat ", pFile, throw DeadlyImportError("Unknown HMP subformat ", pFile,
". Magic word (", szBuffer, ") is not known"); ". Magic word (", szBuffer, ") is not known");

View File

@ -419,7 +419,7 @@ bool OgreImporter::ReadTextureUnit(const std::string &textureUnitName, stringstr
size_t posUnderscore = textureRef.find_last_of("_"); size_t posUnderscore = textureRef.find_last_of("_");
if (posSuffix != string::npos && posUnderscore != string::npos && posSuffix > posUnderscore) { if (posSuffix != string::npos && posUnderscore != string::npos && posSuffix > posUnderscore) {
string identifier = ai_str_tolower(textureRef.substr(posUnderscore, posSuffix - posUnderscore)); string identifier = ai_tolower(textureRef.substr(posUnderscore, posSuffix - posUnderscore));
ASSIMP_LOG_VERBOSE_DEBUG_F("Detecting texture type from filename postfix '", identifier, "'"); ASSIMP_LOG_VERBOSE_DEBUG_F("Detecting texture type from filename postfix '", identifier, "'");
if (identifier == "_n" || identifier == "_nrm" || identifier == "_nrml" || identifier == "_normal" || identifier == "_normals" || identifier == "_normalmap") { if (identifier == "_n" || identifier == "_nrm" || identifier == "_nrml" || identifier == "_normal" || identifier == "_normals" || identifier == "_normalmap") {
@ -440,7 +440,7 @@ bool OgreImporter::ReadTextureUnit(const std::string &textureUnitName, stringstr
// Detect from texture unit name. This cannot be too broad as // Detect from texture unit name. This cannot be too broad as
// authors might give names like "LightSaber" or "NormalNinja". // authors might give names like "LightSaber" or "NormalNinja".
else { else {
string unitNameLower = ai_str_tolower(textureUnitName); string unitNameLower = ai_tolower(textureUnitName);
if (unitNameLower.find("normalmap") != string::npos) { if (unitNameLower.find("normalmap") != string::npos) {
textureType = aiTextureType_NORMALS; textureType = aiTextureType_NORMALS;
} else if (unitNameLower.find("specularmap") != string::npos) { } else if (unitNameLower.find("specularmap") != string::npos) {

View File

@ -64,7 +64,7 @@ static inline bool EndsWith(const std::string &s, const std::string &suffix, boo
} }
if (!caseSensitive) { if (!caseSensitive) {
return EndsWith(ai_str_tolower(s), ai_str_tolower(suffix), true); return EndsWith(ai_tolower(s), ai_tolower(suffix), true);
} }
size_t len = suffix.length(); size_t len = suffix.length();

View File

@ -120,7 +120,7 @@ std::string OgreXmlSerializer::ReadAttribute<std::string>(XmlNode &xmlNode, cons
template <> template <>
bool OgreXmlSerializer::ReadAttribute<bool>(XmlNode &xmlNode, const char *name) const { bool OgreXmlSerializer::ReadAttribute<bool>(XmlNode &xmlNode, const char *name) const {
std::string value = ai_str_tolower(ReadAttribute<std::string>(xmlNode, name)); std::string value = ai_tolower(ReadAttribute<std::string>(xmlNode, name));
if (ASSIMP_stricmp(value, "true") == 0) { if (ASSIMP_stricmp(value, "true") == 0) {
return true; return true;
} else if (ASSIMP_stricmp(value, "false") == 0) { } else if (ASSIMP_stricmp(value, "false") == 0) {
@ -545,7 +545,7 @@ void OgreXmlSerializer::ReadSkeleton(XmlNode &node, Skeleton *skeleton) {
// Optional blend mode from root node // Optional blend mode from root node
if (XmlParser::hasAttribute(node, "blendmode")) { if (XmlParser::hasAttribute(node, "blendmode")) {
skeleton->blendMode = (ai_str_tolower(ReadAttribute<std::string>(node, "blendmode")) == "cumulative" ? Skeleton::ANIMBLEND_CUMULATIVE : Skeleton::ANIMBLEND_AVERAGE); skeleton->blendMode = (ai_tolower(ReadAttribute<std::string>(node, "blendmode")) == "cumulative" ? Skeleton::ANIMBLEND_CUMULATIVE : Skeleton::ANIMBLEND_AVERAGE);
} }
for (XmlNode &currentNode : node.children()) { for (XmlNode &currentNode : node.children()) {

View File

@ -278,7 +278,7 @@ void STEP::ReadFile(DB& db,const EXPRESS::ConversionSchema& scheme,
--ne; --ne;
} while (IsSpace(s.at(ne))); } while (IsSpace(s.at(ne)));
std::string type = s.substr(ns, ne - ns + 1); std::string type = s.substr(ns, ne - ns + 1);
type = ai_str_tolower(type); type = ai_tolower(type);
const char* sz = scheme.GetStaticStringForToken(type); const char* sz = scheme.GetStaticStringForToken(type);
if(sz) { if(sz) {
const std::string::size_type szLen = n2-n1+1; const std::string::size_type szLen = n2-n1+1;

View File

@ -527,8 +527,8 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) {
std::fill(aim->mAnimMeshes, aim->mAnimMeshes + aim->mNumAnimMeshes, nullptr); std::fill(aim->mAnimMeshes, aim->mAnimMeshes + aim->mNumAnimMeshes, nullptr);
for (size_t i = 0; i < targets.size(); i++) { for (size_t i = 0; i < targets.size(); i++) {
bool needPositions = targets[i].position.size() > 0; bool needPositions = targets[i].position.size() > 0;
bool needNormals = targets[i].normal.size() > 0; bool needNormals = (targets[i].normal.size() > 0) && aim->HasNormals();
bool needTangents = targets[i].tangent.size() > 0; bool needTangents = (targets[i].tangent.size() > 0) && aim->HasTangentsAndBitangents();
// GLTF morph does not support colors and texCoords // GLTF morph does not support colors and texCoords
aim->mAnimMeshes[i] = aiCreateAnimMesh(aim, aim->mAnimMeshes[i] = aiCreateAnimMesh(aim,
needPositions, needNormals, needTangents, false, false); needPositions, needNormals, needTangents, false, false);
@ -536,6 +536,9 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) {
Mesh::Primitive::Target &target = targets[i]; Mesh::Primitive::Target &target = targets[i];
if (needPositions) { if (needPositions) {
if (target.position[0]->count != aim->mNumVertices) {
ASSIMP_LOG_WARN_F("Positions of target ", i, " in mesh \"", mesh.name, "\" does not match the vertex count");
} else {
aiVector3D *positionDiff = nullptr; aiVector3D *positionDiff = nullptr;
target.position[0]->ExtractData(positionDiff); target.position[0]->ExtractData(positionDiff);
for (unsigned int vertexId = 0; vertexId < aim->mNumVertices; vertexId++) { for (unsigned int vertexId = 0; vertexId < aim->mNumVertices; vertexId++) {
@ -543,7 +546,11 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) {
} }
delete[] positionDiff; delete[] positionDiff;
} }
}
if (needNormals) { if (needNormals) {
if (target.normal[0]->count != aim->mNumVertices) {
ASSIMP_LOG_WARN_F("Normals of target ", i, " in mesh \"", mesh.name, "\" does not match the vertex count");
} else {
aiVector3D *normalDiff = nullptr; aiVector3D *normalDiff = nullptr;
target.normal[0]->ExtractData(normalDiff); target.normal[0]->ExtractData(normalDiff);
for (unsigned int vertexId = 0; vertexId < aim->mNumVertices; vertexId++) { for (unsigned int vertexId = 0; vertexId < aim->mNumVertices; vertexId++) {
@ -551,7 +558,11 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) {
} }
delete[] normalDiff; delete[] normalDiff;
} }
}
if (needTangents) { if (needTangents) {
if (target.tangent[0]->count != aim->mNumVertices) {
ASSIMP_LOG_WARN_F("Tangents of target ", i, " in mesh \"", mesh.name, "\" does not match the vertex count");
} else {
Tangent *tangent = nullptr; Tangent *tangent = nullptr;
attr.tangent[0]->ExtractData(tangent); attr.tangent[0]->ExtractData(tangent);
@ -566,6 +577,7 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) {
delete[] tangent; delete[] tangent;
delete[] tangentDiff; delete[] tangentDiff;
} }
}
if (mesh.weights.size() > i) { if (mesh.weights.size() > i) {
aiAnimMesh.mWeight = mesh.weights[i]; aiAnimMesh.mWeight = mesh.weights[i];
} }

View File

@ -298,7 +298,6 @@ SET(ASSIMP_EXPORTERS_DISABLED "") # disabled exporters list (used to print)
ADD_ASSIMP_IMPORTER( AMF ADD_ASSIMP_IMPORTER( AMF
AssetLib/AMF/AMFImporter.hpp AssetLib/AMF/AMFImporter.hpp
AssetLib/AMF/AMFImporter_Macro.hpp
AssetLib/AMF/AMFImporter_Node.hpp AssetLib/AMF/AMFImporter_Node.hpp
AssetLib/AMF/AMFImporter.cpp AssetLib/AMF/AMFImporter.cpp
AssetLib/AMF/AMFImporter_Geometry.cpp AssetLib/AMF/AMFImporter_Geometry.cpp

View File

@ -276,7 +276,7 @@ std::string BaseImporter::GetExtension(const std::string &file) {
// thanks to Andy Maloney for the hint // thanks to Andy Maloney for the hint
std::string ret = file.substr(pos + 1); std::string ret = file.substr(pos + 1);
ret = ai_str_tolower(ret); ret = ai_tolower(ret);
return ret; return ret;
} }

View File

@ -982,7 +982,7 @@ size_t Importer::GetImporterIndex (const char* szExtension) const {
if (ext.empty()) { if (ext.empty()) {
return static_cast<size_t>(-1); return static_cast<size_t>(-1);
} }
ext = ai_str_tolower(ext); ext = ai_tolower(ext);
std::set<std::string> str; std::set<std::string> str;
for (std::vector<BaseImporter*>::const_iterator i = pimpl->mImporter.begin();i != pimpl->mImporter.end();++i) { for (std::vector<BaseImporter*>::const_iterator i = pimpl->mImporter.begin();i != pimpl->mImporter.end();++i) {
str.clear(); str.clear();

View File

@ -137,7 +137,7 @@ bool EmbedTexturesProcess::addTexture(aiScene* pScene, std::string path) const {
pTexture->pcData = imageContent; pTexture->pcData = imageContent;
auto extension = path.substr(path.find_last_of('.') + 1u); auto extension = path.substr(path.find_last_of('.') + 1u);
extension = ai_str_tolower(extension); extension = ai_tolower(extension);
if (extension == "jpeg") { if (extension == "jpeg") {
extension = "jpg"; extension = "jpg";
} }

View File

@ -97,7 +97,7 @@ inline T getEpsilon() {
/// @brief Will return the constant PI for the requested type. /// @brief Will return the constant PI for the requested type.
/// @return Pi /// @return Pi
template<class T> template<class T>
inline T PI() { inline T aiPi() {
return static_cast<T>(3.14159265358979323846); return static_cast<T>(3.14159265358979323846);
} }

View File

@ -225,7 +225,7 @@ AI_FORCE_INLINE char_t ai_tolower(char_t in) {
/// @param in The incoming string. /// @param in The incoming string.
/// @return The string as lowercase. /// @return The string as lowercase.
// --------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------
AI_FORCE_INLINE std::string ai_str_tolower(const std::string &in) { AI_FORCE_INLINE std::string ai_tolower(const std::string &in) {
std::string out(in); std::string out(in);
ai_trim_left(out); ai_trim_left(out);
ai_trim_right(out); ai_trim_right(out);

View File

@ -22,7 +22,7 @@ BUILD_TYPE=Release
################################################ ################################################
# Minimum iOS deployment target version # Minimum iOS deployment target version
################################################ ################################################
MIN_IOS_VERSION="6.0" MIN_IOS_VERSION="10.0"
IOS_SDK_TARGET=$MIN_IOS_VERSION IOS_SDK_TARGET=$MIN_IOS_VERSION
XCODE_ROOT_DIR=$(xcode-select --print-path) XCODE_ROOT_DIR=$(xcode-select --print-path)
@ -60,8 +60,8 @@ build_arch()
unset DEVROOT SDKROOT CFLAGS LDFLAGS CPPFLAGS CXXFLAGS CMAKE_CLI_INPUT unset DEVROOT SDKROOT CFLAGS LDFLAGS CPPFLAGS CXXFLAGS CMAKE_CLI_INPUT
#export CC="$(xcrun -sdk iphoneos -find clang)" export CC="$(xcrun -sdk iphoneos -find clang)"
#export CPP="$CC -E" export CPP="$CC -E"
export DEVROOT=$XCODE_ROOT_DIR/Platforms/$IOS_SDK_DEVICE.platform/Developer export DEVROOT=$XCODE_ROOT_DIR/Platforms/$IOS_SDK_DEVICE.platform/Developer
export SDKROOT=$DEVROOT/SDKs/$IOS_SDK_DEVICE$IOS_SDK_VERSION.sdk export SDKROOT=$DEVROOT/SDKs/$IOS_SDK_DEVICE$IOS_SDK_VERSION.sdk
export CFLAGS="-arch $1 -pipe -no-cpp-precomp -stdlib=$CPP_STD_LIB -isysroot $SDKROOT -I$SDKROOT/usr/include/ -miphoneos-version-min=$IOS_SDK_TARGET" export CFLAGS="-arch $1 -pipe -no-cpp-precomp -stdlib=$CPP_STD_LIB -isysroot $SDKROOT -I$SDKROOT/usr/include/ -miphoneos-version-min=$IOS_SDK_TARGET"

View File

@ -105,7 +105,7 @@ void CLogWindow::Init() {
// setup the log text // setup the log text
this->szText = AI_VIEW_RTF_LOG_HEADER; this->szText = AI_VIEW_RTF_LOG_HEADER;
;
this->szPlainText = ""; this->szPlainText = "";
} }