Merge branch 'master' into MalcolmTyrrell/tangentCheck

pull/3718/head
Kim Kulling 2021-04-03 17:42:44 +02:00 committed by GitHub
commit 22413d85ad
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 255 additions and 324 deletions

1
.github/FUNDING.yml vendored
View File

@ -1,2 +1 @@
patreon: assimp
open_collective: assimp

3
.gitignore vendored
View File

@ -116,3 +116,6 @@ tools/assimp_qt_viewer/moc_glview.cpp_parameters
tools/assimp_qt_viewer/moc_mainwindow.cpp
tools/assimp_qt_viewer/moc_mainwindow.cpp_parameters
tools/assimp_qt_viewer/ui_mainwindow.h
#Generated directory
generated/*

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

@ -444,7 +444,7 @@ void Discreet3DSExporter::WriteMeshes() {
const uint16_t count = static_cast<uint16_t>(mesh.mNumVertices);
writer.PutU2(count);
for (unsigned int i = 0; i < mesh.mNumVertices; ++i) {
const aiVector3D &v = trafo * mesh.mVertices[i];
const aiVector3D &v = mesh.mVertices[i];
writer.PutF4(v.x);
writer.PutF4(v.y);
writer.PutF4(v.z);
@ -506,11 +506,16 @@ void Discreet3DSExporter::WriteMeshes() {
// Transformation matrix by which the mesh vertices have been pre-transformed with.
{
ChunkWriter curChunk(writer, Discreet3DS::CHUNK_TRMATRIX);
for (unsigned int r = 0; r < 4; ++r) {
// Store rotation 3x3 matrix row wise
for (unsigned int r = 0; r < 3; ++r) {
for (unsigned int c = 0; c < 3; ++c) {
writer.PutF4(trafo[r][c]);
}
}
// Store translation sub vector column wise
for (unsigned int r = 0; r < 3; ++r) {
writer.PutF4(trafo[r][3]);
}
}
}
}

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

@ -1,164 +0,0 @@
/*
---------------------------------------------------------------------------
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2021, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other
materials provided with the distribution.
* Neither the name of the assimp team, nor the names of its
contributors may be used to endorse or promote products
derived from this software without specific prior
written permission of the assimp team.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
/// \file AMFImporter_Macro.hpp
/// \brief Useful macrodefines.
/// \date 2016
/// \author smal.root@gmail.com
#pragma once
#ifndef AMFIMPORTER_MACRO_HPP_INCLUDED
#define AMFIMPORTER_MACRO_HPP_INCLUDED
/// \def MACRO_ATTRREAD_LOOPBEG
/// Begin of loop that read attributes values.
#define MACRO_ATTRREAD_LOOPBEG \
for(int idx = 0, idx_end = mReader->getAttributeCount(); idx < idx_end; idx++) \
{ \
std::string an(mReader->getAttributeName(idx));
/// \def MACRO_ATTRREAD_LOOPEND
/// End of loop that read attributes values.
#define MACRO_ATTRREAD_LOOPEND \
Throw_IncorrectAttr(an); \
}
/// \def MACRO_ATTRREAD_LOOPEND_WSKIP
/// End of loop that read attributes values. Difference from \ref MACRO_ATTRREAD_LOOPEND in that: current macro skip unknown attributes, but
/// \ref MACRO_ATTRREAD_LOOPEND throw an exception.
#define MACRO_ATTRREAD_LOOPEND_WSKIP \
continue; \
}
/// \def MACRO_ATTRREAD_CHECK_REF
/// Check current attribute name and if it equal to requested then read value. Result write to output variable by reference. If result was read then
/// "continue" will called.
/// \param [in] pAttrName - attribute name.
/// \param [out] pVarName - output variable name.
/// \param [in] pFunction - function which read attribute value and write it to pVarName.
#define MACRO_ATTRREAD_CHECK_REF(pAttrName, pVarName, pFunction) \
if(an == pAttrName) \
{ \
pFunction(idx, pVarName); \
continue; \
}
/// \def MACRO_ATTRREAD_CHECK_RET
/// Check current attribute name and if it equal to requested then read value. Result write to output variable using return value of \ref pFunction.
/// If result was read then "continue" will called.
/// \param [in] pAttrName - attribute name.
/// \param [out] pVarName - output variable name.
/// \param [in] pFunction - function which read attribute value and write it to pVarName.
#define MACRO_ATTRREAD_CHECK_RET(pAttrName, pVarName, pFunction) \
if(an == pAttrName) \
{ \
pVarName = pFunction(idx); \
continue; \
}
/// \def MACRO_NODECHECK_LOOPBEGIN(pNodeName)
/// Begin of loop of parsing child nodes. Do not add ';' at end.
/// \param [in] pNodeName - current node name.
#define MACRO_NODECHECK_LOOPBEGIN(pNodeName) \
do { \
bool close_found = false; \
\
while(mReader->read()) \
{ \
if(mReader->getNodeType() == irr::io::EXN_ELEMENT) \
{
/// \def MACRO_NODECHECK_LOOPEND(pNodeName)
/// End of loop of parsing child nodes.
/// \param [in] pNodeName - current node name.
#define MACRO_NODECHECK_LOOPEND(pNodeName) \
XML_CheckNode_SkipUnsupported(pNodeName); \
}/* if(mReader->getNodeType() == irr::io::EXN_ELEMENT) */ \
else if(mReader->getNodeType() == irr::io::EXN_ELEMENT_END) \
{ \
if(XML_CheckNode_NameEqual(pNodeName)) \
{ \
close_found = true; \
\
break; \
} \
}/* else if(mReader->getNodeType() == irr::io::EXN_ELEMENT_END) */ \
}/* while(mReader->read()) */ \
\
if(!close_found) Throw_CloseNotFound(pNodeName); \
\
} while(false)
/// \def MACRO_NODECHECK_READCOMP_F
/// Check current node name and if it equal to requested then read value. Result write to output variable of type "float".
/// If result was read then "continue" will called. Also check if node data already read then raise exception.
/// \param [in] pNodeName - node name.
/// \param [in, out] pReadFlag - read flag.
/// \param [out] pVarName - output variable name.
#define MACRO_NODECHECK_READCOMP_F(pNodeName, pReadFlag, pVarName) \
if(XML_CheckNode_NameEqual(pNodeName)) \
{ \
/* Check if field already read before. */ \
if(pReadFlag) Throw_MoreThanOnceDefined(pNodeName, "Only one component can be defined."); \
/* Read color component and assign it to object. */ \
pVarName = XML_ReadNode_GetVal_AsFloat(); \
pReadFlag = true; \
continue; \
}
/// \def MACRO_NODECHECK_READCOMP_U32
/// Check current node name and if it equal to requested then read value. Result write to output variable of type "uint32_t".
/// If result was read then "continue" will called. Also check if node data already read then raise exception.
/// \param [in] pNodeName - node name.
/// \param [in, out] pReadFlag - read flag.
/// \param [out] pVarName - output variable name.
#define MACRO_NODECHECK_READCOMP_U32(pNodeName, pReadFlag, pVarName) \
if(XML_CheckNode_NameEqual(pNodeName)) \
{ \
/* Check if field already read before. */ \
if(pReadFlag) Throw_MoreThanOnceDefined(pNodeName, "Only one component can be defined."); \
/* Read color component and assign it to object. */ \
pVarName = XML_ReadNode_GetVal_AsU32(); \
pReadFlag = true; \
continue; \
}
#endif // AMFIMPORTER_MACRO_HPP_INCLUDED

View File

@ -65,48 +65,45 @@ 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();
// create new color object.
AMFNodeElementBase *ne = new AMFColor(mNodeElement_Cur);
AMFColor& als = *((AMFColor*)ne);// alias for convenience
if (node.empty()) {
return;
}
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();
if ( name == "r") {
read_flag[0] = true;
XmlParser::getValueAsFloat(child, als.Color.r);
} else if (name == "g") {
read_flag[1] = true;
XmlParser::getValueAsFloat(child, als.Color.g);
} else if (name == "b") {
read_flag[2] = true;
XmlParser::getValueAsFloat(child, als.Color.b);
} else if (name == "a") {
read_flag[3] = true;
XmlParser::getValueAsFloat(child, als.Color.a);
}
ParseHelper_Node_Exit();
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
ParseHelper_Node_Enter(ne);
for (pugi::xml_node &child : node.children()) {
// 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);
} else if (name == "g") {
read_flag[1] = true;
XmlParser::getValueAsFloat(child, als.Color.g);
} else if (name == "b") {
read_flag[2] = true;
XmlParser::getValueAsFloat(child, als.Color.b);
} else if (name == "a") {
read_flag[3] = true;
XmlParser::getValueAsFloat(child, als.Color.a);
}
// 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
// check if <a> is absent. Then manually add "a == 1".
if (!read_flag[3]) {
als.Color.a = 1;
}
}
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.");
}
als.Composed = false;
mNodeElement_List.push_back(ne);// and to node element list because its a new object in graph.
}
// <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();
uint32_t depth = node.attribute("depth").as_uint();
std::string type = node.attribute("type").as_string();
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();
const std::string type = node.attribute("type").as_string();
bool tiled = node.attribute("tiled").as_bool();
if (node.empty()) {
@ -174,22 +171,20 @@ void AMFImporter::ParseNode_Texture(XmlNode &node) {
AMFTexture& als = *((AMFTexture*)ne);// alias for convenience
std::string enc64_data = node.value();
// Check for child nodes
std::string enc64_data;
XmlParser::getValueAsString(node, enc64_data);
// Check for child nodes
// check that all components was defined
if (id.empty()) {
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

@ -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

@ -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

@ -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 = "";
}