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()
# If the zlib is already found outside, add an export in case assimpTargets can't find it.
IF( ZLIB_FOUND )
INSTALL( TARGETS zlib
INSTALL( TARGETS zlib zlibstatic
EXPORT "${TARGETS_EXPORT_NAME}")
ENDIF()

View File

@ -1,6 +1,6 @@
Open Asset Import Library (assimp)
Copyright (c) 2006-2020, assimp team
Copyright (c) 2006-2021, assimp team
All rights reserved.
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.
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.
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>
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

View File

@ -981,9 +981,9 @@ void Discreet3DSImporter::ParseMeshChunk() {
mMesh.mMat.a3 = stream->GetF4();
mMesh.mMat.b3 = stream->GetF4();
mMesh.mMat.c3 = stream->GetF4();
mMesh.mMat.a4 = stream->GetF4();
mMesh.mMat.b4 = stream->GetF4();
mMesh.mMat.c4 = stream->GetF4();
mMesh.mMat.d1 = stream->GetF4();
mMesh.mMat.d2 = stream->GetF4();
mMesh.mMat.d3 = stream->GetF4();
} break;
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
// Header files, Assimp.
#include "AMFImporter.hpp"
#include "AMFImporter_Macro.hpp"
#include <assimp/DefaultIOSystem.h>
#include <assimp/fast_atof.h>
@ -307,14 +301,14 @@ void AMFImporter::ParseNode_Root() {
throw DeadlyImportError("Root node \"amf\" not found.");
}
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();
// Read attributes for node <amf>.
// Check attributes
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);
}
}
@ -409,20 +403,20 @@ void AMFImporter::ParseNode_Instance(XmlNode &node) {
if (!node.empty()) {
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();
if (currentName == "deltax") {
als.Delta.x = (ai_real)std::atof(currentNode.value());
XmlParser::getValueAsFloat(currentNode, als.Delta.x);
} else if (currentName == "deltay") {
als.Delta.y = (ai_real)std::atof(currentNode.value());
XmlParser::getValueAsFloat(currentNode, als.Delta.y);
} else if (currentName == "deltaz") {
als.Delta.z = (ai_real)std::atof(currentNode.value());
XmlParser::getValueAsFloat(currentNode, als.Delta.z);
} else if (currentName == "rx") {
als.Delta.x = (ai_real)std::atof(currentNode.value());
XmlParser::getValueAsFloat(currentNode, als.Delta.x);
} else if (currentName == "ry") {
als.Delta.y = (ai_real)std::atof(currentNode.value());
XmlParser::getValueAsFloat(currentNode, als.Delta.y);
} else if (currentName == "rz") {
als.Delta.z = (ai_real)std::atof(currentNode.value());
XmlParser::getValueAsFloat(currentNode, als.Delta.z);
}
}
ParseHelper_Node_Exit();
@ -458,7 +452,7 @@ void AMFImporter::ParseNode_Object(XmlNode &node) {
// Check for child nodes
if (!node.empty()) {
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();
if (currentName == "color") {
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
#include "AMFImporter.hpp"
#include "AMFImporter_Macro.hpp"
#include <assimp/ParsingUtils.h>
namespace Assimp {
@ -103,18 +96,18 @@ void AMFImporter::ParseNode_Vertices(XmlNode &node) {
// create new mesh object.
ne = new AMFVertices(mNodeElement_Cur);
// Check for child nodes
pugi::xml_node vertexNode = node.child("vertex");
if (!vertexNode.empty()) {
ParseHelper_Node_Enter(ne);
ParseNode_Vertex(vertexNode);
ParseHelper_Node_Exit();
} else {
if (node.empty()) {
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.
}
@ -166,27 +159,25 @@ void AMFImporter::ParseNode_Vertex(XmlNode &node) {
// X, Y, or Z coordinate, respectively, of a vertex position in space.
void AMFImporter::ParseNode_Coordinates(XmlNode &node) {
AMFNodeElementBase *ne = nullptr;
// create new color object.
ne = new AMFCoordinates(mNodeElement_Cur);
AMFCoordinates &als = *((AMFCoordinates *)ne); // alias for convenience
if (!node.empty()) {
ne = new AMFCoordinates(mNodeElement_Cur);
ParseHelper_Node_Enter(ne);
for (XmlNode &currentNode : node.children()) {
const std::string &currentName = currentNode.name();
if (currentName == "X") {
// create new color object.
AMFCoordinates &als = *((AMFCoordinates *)ne); // alias for convenience
const std::string &currentName = ai_tolower(currentNode.name());
if (currentName == "x") {
XmlParser::getValueAsFloat(currentNode, als.Coordinate.x);
} else if (currentName == "Y") {
} else if (currentName == "y") {
XmlParser::getValueAsFloat(currentNode, als.Coordinate.y);
} else if (currentName == "Z") {
} else if (currentName == "z") {
XmlParser::getValueAsFloat(currentNode, als.Coordinate.z);
}
}
ParseHelper_Node_Exit();
} 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.
@ -216,7 +207,7 @@ void AMFImporter::ParseNode_Volume(XmlNode &node) {
bool col_read = false;
if (!node.empty()) {
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();
if (currentName == "color") {
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;
if (!node.empty()) {
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();
if (currentName == "color") {
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") {
ParseNode_TexMap(currentNode, true);
} 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") {
als.V[1] = std::atoi(currentNode.value());
XmlParser::getValueAsString(currentNode, v);
als.V[1] = std::atoi(v.c_str());
} 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();

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
// values can be specified as constants, or as a formula depending on the coordinates.
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();
bool read_flag[4] = { false, false, false, false };
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 };
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") {
read_flag[0] = true;
XmlParser::getValueAsFloat(child, als.Color.r);
@ -90,23 +92,18 @@ void AMFImporter::ParseNode_Color(XmlNode &node) {
read_flag[3] = true;
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".
if (!read_flag[3]) {
als.Color.a = 1;
}
} else {
mNodeElement_Cur->Child.push_back(ne);// Add element to child list of current element
}
als.Composed = false;
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
@ -158,11 +155,11 @@ void AMFImporter::ParseNode_Material(XmlNode &node) {
// Multi elements - Yes.
// Parent element - <amf>.
void AMFImporter::ParseNode_Texture(XmlNode &node) {
std::string id = node.attribute("id").as_string();
uint32_t width = node.attribute("width").as_uint();
uint32_t height = node.attribute("height").as_uint();
const std::string id = node.attribute("id").as_string();
const uint32_t width = node.attribute("width").as_uint();
const uint32_t height = node.attribute("height").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();
if (node.empty()) {
@ -174,7 +171,8 @@ void AMFImporter::ParseNode_Texture(XmlNode &node) {
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 that all components was defined
@ -182,14 +180,11 @@ void AMFImporter::ParseNode_Texture(XmlNode &node) {
throw DeadlyImportError("ID for texture must be defined.");
}
if (width < 1) {
throw DeadlyImportError("INvalid width for texture.");
throw DeadlyImportError("Invalid width for texture.");
}
if (height < 1) {
throw DeadlyImportError("Invalid height for texture.");
}
if (depth < 1) {
throw DeadlyImportError("Invalid depth for texture.");
}
if (type != "grayscale") {
throw DeadlyImportError("Invalid type for texture.");
}
@ -203,7 +198,9 @@ void AMFImporter::ParseNode_Texture(XmlNode &node) {
als.Depth = depth;
als.Tiled = tiled;
ParseHelper_Decode_Base64(enc64_data, als.Data);
if (depth == 0) {
depth = (uint32_t)(als.Data.size() / (width * height));
}
// check data size
if ((width * height * depth) != als.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); //
std::string rtexid, gtexid, btexid, atexid;
if (!node.empty()) {
ParseHelper_Node_Enter(ne);
for (XmlNode &currentNode : node.children()) {
const std::string &currentName = currentNode.name();
if (currentName == "rtexid") {
XmlParser::getValueAsString(node, rtexid);
} else if (currentName == "gtexid") {
XmlParser::getValueAsString(node, gtexid);
} else if (currentName == "btexid") {
XmlParser::getValueAsString(node, btexid);
} else if (currentName == "atexid") {
XmlParser::getValueAsString(node, atexid);
for (pugi::xml_attribute &attr : node.attributes()) {
const std::string &currentAttr = attr.name();
if (currentAttr == "rtexid") {
rtexid = attr.as_string();
} else if (currentAttr == "gtexid") {
gtexid = attr.as_string();
} else if (currentAttr == "btexid") {
btexid = attr.as_string();
} else if (currentAttr == "atexid") {
atexid = attr.as_string();
}
}
ParseHelper_Node_Exit();
}
// 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
//XML_CheckNode_MustHaveChildren();
if (node.children().begin() == node.children().end()) {
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 };
if (!pUseOldName) {
for (pugi::xml_attribute &attr : node.attributes()) {
const std::string name = attr.name();
ParseHelper_Node_Enter(ne);
for ( XmlNode &currentNode : node.children()) {
const std::string &name = currentNode.name();
if (name == "utex1") {
read_flag[0] = true;
als.TextureCoordinate[0].x = attr.as_float();
XmlParser::getValueAsFloat(node, als.TextureCoordinate[0].x);
} else if (name == "utex2") {
read_flag[1] = true;
als.TextureCoordinate[1].x = attr.as_float();
XmlParser::getValueAsFloat(node, als.TextureCoordinate[1].x);
} else if (name == "utex3") {
read_flag[2] = true;
als.TextureCoordinate[2].x = attr.as_float();
XmlParser::getValueAsFloat(node, als.TextureCoordinate[2].x);
} else if (name == "vtex1") {
read_flag[3] = true;
als.TextureCoordinate[0].y = attr.as_float();
XmlParser::getValueAsFloat(node, als.TextureCoordinate[0].y);
} else if (name == "vtex2") {
read_flag[4] = true;
als.TextureCoordinate[1].y = attr.as_float();
XmlParser::getValueAsFloat(node, als.TextureCoordinate[1].y);
} else if (name == "vtex3") {
read_flag[5] = true;
als.TextureCoordinate[0].y = attr.as_float();
XmlParser::getValueAsFloat(node, als.TextureCoordinate[2].y);
}
}
ParseHelper_Node_Exit();
} else {
for (pugi::xml_attribute &attr : node.attributes()) {
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.
if (!Composition.empty()) {
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
if ((tcol.r == 0) && (tcol.g == 0) && (tcol.b == 0) && (tcol.a == 0)) {
tcol.r = 0.5f;
@ -79,13 +81,13 @@ aiColor4D AMFImporter::SPP_Material::GetColor(const float /*pX*/, const float /*
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 {
AMFVertices *vn = nullptr;
size_t col_idx;
// 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) {
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.
pVertexCoordinateArray.reserve(vn->Child.size());
vertexCoordinateArray.reserve(vn->Child.size());
// colors count equal vertices count.
pVertexColorArray.resize(vn->Child.size());
@ -112,7 +114,7 @@ void AMFImporter::PostprocessHelper_CreateMeshDataArray(const AMFMesh &pNodeElem
for (AMFNodeElementBase *vtx : vn_child->Child) {
if (vtx->Type == AMFNodeElementBase::ENET_Coordinates) {
pVertexCoordinateArray.push_back(((AMFCoordinates *)vtx)->Coordinate);
vertexCoordinateArray.push_back(((AMFCoordinates *)vtx)->Coordinate);
continue;
}

View File

@ -812,6 +812,18 @@ void FBXExporter::WriteDefinitions ()
// Geometry / FbxMesh
// <~~ aiMesh
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) {
n = FBX::Node("ObjectType", "Geometry");
n.AddChild("Count", count);
@ -978,7 +990,7 @@ void FBXExporter::WriteDefinitions ()
}
// Deformer
count = int32_t(count_deformers(mScene));
count = int32_t(count_deformers(mScene))+bsDeformerCount;
if (count) {
n = FBX::Node("ObjectType", "Deformer");
n.AddChild("Count", count);
@ -1363,6 +1375,7 @@ void FBXExporter::WriteObjects ()
n.End(outstream, binary, indent, true);
}
// aiMaterial
material_uids.clear();
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.
//
// output structure:

View File

@ -158,6 +158,9 @@ void HMPImporter::InternReadFile(const std::string &pFile,
szBuffer[3] = ((char *)&iMagic)[3];
szBuffer[4] = '\0';
delete[] mBuffer;
mBuffer = nullptr;
// We're definitely unable to load this file
throw DeadlyImportError("Unknown HMP subformat ", pFile,
". 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("_");
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, "'");
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
// authors might give names like "LightSaber" or "NormalNinja".
else {
string unitNameLower = ai_str_tolower(textureUnitName);
string unitNameLower = ai_tolower(textureUnitName);
if (unitNameLower.find("normalmap") != string::npos) {
textureType = aiTextureType_NORMALS;
} 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) {
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();

View File

@ -120,7 +120,7 @@ std::string OgreXmlSerializer::ReadAttribute<std::string>(XmlNode &xmlNode, cons
template <>
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) {
return true;
} else if (ASSIMP_stricmp(value, "false") == 0) {
@ -545,7 +545,7 @@ void OgreXmlSerializer::ReadSkeleton(XmlNode &node, Skeleton *skeleton) {
// Optional blend mode from root node
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()) {

View File

@ -278,7 +278,7 @@ void STEP::ReadFile(DB& db,const EXPRESS::ConversionSchema& scheme,
--ne;
} while (IsSpace(s.at(ne)));
std::string type = s.substr(ns, ne - ns + 1);
type = ai_str_tolower(type);
type = ai_tolower(type);
const char* sz = scheme.GetStaticStringForToken(type);
if(sz) {
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);
for (size_t i = 0; i < targets.size(); i++) {
bool needPositions = targets[i].position.size() > 0;
bool needNormals = targets[i].normal.size() > 0;
bool needTangents = targets[i].tangent.size() > 0;
bool needNormals = (targets[i].normal.size() > 0) && aim->HasNormals();
bool needTangents = (targets[i].tangent.size() > 0) && aim->HasTangentsAndBitangents();
// GLTF morph does not support colors and texCoords
aim->mAnimMeshes[i] = aiCreateAnimMesh(aim,
needPositions, needNormals, needTangents, false, false);
@ -536,6 +536,9 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) {
Mesh::Primitive::Target &target = targets[i];
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;
target.position[0]->ExtractData(positionDiff);
for (unsigned int vertexId = 0; vertexId < aim->mNumVertices; vertexId++) {
@ -543,7 +546,11 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) {
}
delete[] positionDiff;
}
}
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;
target.normal[0]->ExtractData(normalDiff);
for (unsigned int vertexId = 0; vertexId < aim->mNumVertices; vertexId++) {
@ -551,7 +558,11 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) {
}
delete[] normalDiff;
}
}
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;
attr.tangent[0]->ExtractData(tangent);
@ -566,6 +577,7 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) {
delete[] tangent;
delete[] tangentDiff;
}
}
if (mesh.weights.size() > 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
AssetLib/AMF/AMFImporter.hpp
AssetLib/AMF/AMFImporter_Macro.hpp
AssetLib/AMF/AMFImporter_Node.hpp
AssetLib/AMF/AMFImporter.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
std::string ret = file.substr(pos + 1);
ret = ai_str_tolower(ret);
ret = ai_tolower(ret);
return ret;
}

View File

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

View File

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

View File

@ -97,7 +97,7 @@ inline T getEpsilon() {
/// @brief Will return the constant PI for the requested type.
/// @return Pi
template<class T>
inline T PI() {
inline T aiPi() {
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.
/// @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);
ai_trim_left(out);
ai_trim_right(out);

View File

@ -22,7 +22,7 @@ BUILD_TYPE=Release
################################################
# Minimum iOS deployment target version
################################################
MIN_IOS_VERSION="6.0"
MIN_IOS_VERSION="10.0"
IOS_SDK_TARGET=$MIN_IOS_VERSION
XCODE_ROOT_DIR=$(xcode-select --print-path)
@ -60,8 +60,8 @@ build_arch()
unset DEVROOT SDKROOT CFLAGS LDFLAGS CPPFLAGS CXXFLAGS CMAKE_CLI_INPUT
#export CC="$(xcrun -sdk iphoneos -find clang)"
#export CPP="$CC -E"
export CC="$(xcrun -sdk iphoneos -find clang)"
export CPP="$CC -E"
export DEVROOT=$XCODE_ROOT_DIR/Platforms/$IOS_SDK_DEVICE.platform/Developer
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"

View File

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