Merge branch 'master' into refactor/KHR_material_specular

pull/4786/head
Kim Kulling 2023-05-22 09:49:01 +02:00 committed by GitHub
commit e947471549
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
141 changed files with 20671 additions and 1072 deletions

View File

@ -138,7 +138,7 @@ IF (WIN32)
ELSE()
OPTION( ASSIMP_BUILD_ZLIB
"Build your own zlib"
OFF
ON
)
ENDIF()

View File

@ -397,10 +397,6 @@ struct Material {
Material(const Material &other) = default;
Material(Material &&other) AI_NO_EXCEPT = default;
Material &operator=(Material &&other) AI_NO_EXCEPT = default;
virtual ~Material() = default;
//! Name of the material

View File

@ -266,8 +266,15 @@ void Discreet3DSImporter::ParseMainChunk() {
};
ASSIMP_3DS_END_CHUNK();
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunreachable-code-return"
#endif
// recursively continue processing this hierarchy level
return ParseMainChunk();
#if defined(__clang__)
#pragma clang diagnostic pop
#endif
}
// ------------------------------------------------------------------------------------------------

View File

@ -68,7 +68,7 @@ using namespace D3DS;
class Discreet3DSImporter : public BaseImporter {
public:
Discreet3DSImporter();
~Discreet3DSImporter();
~Discreet3DSImporter() override;
// -------------------------------------------------------------------
/** Returns whether the class can handle the format of the given file.

View File

@ -93,7 +93,7 @@ public:
// empty
}
~EmbeddedTexture() = default;
~EmbeddedTexture() override = default;
ResourceType getType() const override {
return ResourceType::RT_EmbeddedTexture2D;
@ -110,7 +110,7 @@ public:
// empty
}
~Texture2DGroup() = default;
~Texture2DGroup() override = default;
ResourceType getType() const override {
return ResourceType::RT_Texture2DGroup;
@ -127,7 +127,7 @@ public:
// empty
}
~BaseMaterials() = default;
~BaseMaterials() override = default;
ResourceType getType() const override {
return ResourceType::RT_BaseMaterials;
@ -152,7 +152,7 @@ public:
// empty
}
~Object() = default;
~Object() override = default;
ResourceType getType() const override {
return ResourceType::RT_Object;

View File

@ -282,11 +282,11 @@ public:
bool Find_NodeElement(const std::string &pID, const AMFNodeElementBase::EType pType, AMFNodeElementBase **pNodeElement) const;
bool Find_ConvertedNode(const std::string &pID, NodeArray &nodeArray, aiNode **pNode) const;
bool Find_ConvertedMaterial(const std::string &pID, const SPP_Material **pConvertedMaterial) const;
void Throw_CloseNotFound(const std::string &nodeName);
void Throw_IncorrectAttr(const std::string &nodeName, const std::string &pAttrName);
void Throw_IncorrectAttrValue(const std::string &nodeName, const std::string &pAttrName);
void Throw_MoreThanOnceDefined(const std::string &nodeName, const std::string &pNodeType, const std::string &pDescription);
void Throw_ID_NotFound(const std::string &pID) const;
AI_WONT_RETURN void Throw_CloseNotFound(const std::string &nodeName) AI_WONT_RETURN_SUFFIX;
AI_WONT_RETURN void Throw_IncorrectAttr(const std::string &nodeName, const std::string &pAttrName) AI_WONT_RETURN_SUFFIX;
AI_WONT_RETURN void Throw_IncorrectAttrValue(const std::string &nodeName, const std::string &pAttrName) AI_WONT_RETURN_SUFFIX;
AI_WONT_RETURN void Throw_MoreThanOnceDefined(const std::string &nodeName, const std::string &pNodeType, const std::string &pDescription) AI_WONT_RETURN_SUFFIX;
AI_WONT_RETURN void Throw_ID_NotFound(const std::string &pID) const AI_WONT_RETURN_SUFFIX;
void XML_CheckNode_MustHaveChildren(pugi::xml_node &node);
bool XML_SearchNode(const std::string &nodeName);
void ParseHelper_FixTruncatedFloatString(const char *pInStr, std::string &pOutString);

View File

@ -44,7 +44,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef ASSIMP_BUILD_NO_ASE_IMPORTER
#ifndef ASSIMP_BUILD_NO_3DS_IMPORTER
// internal headers
@ -322,21 +321,6 @@ void ASEImporter::BuildAnimations(const std::vector<BaseNode *> &nodes) {
aiNodeAnim *nd = pcAnim->mChannels[iNum++] = new aiNodeAnim();
nd->mNodeName.Set(me->mName + ".Target");
// If there is no input position channel we will need
// to supply the default position from the node's
// local transformation matrix.
/*TargetAnimationHelper helper;
if (me->mAnim.akeyPositions.empty())
{
aiMatrix4x4& mat = (*i)->mTransform;
helper.SetFixedMainAnimationChannel(aiVector3D(
mat.a4, mat.b4, mat.c4));
}
else helper.SetMainAnimationChannel (&me->mAnim.akeyPositions);
helper.SetTargetAnimationChannel (&me->mTargetAnim.akeyPositions);
helper.Process(&me->mTargetAnim.akeyPositions);*/
// Allocate the key array and fill it
nd->mNumPositionKeys = (unsigned int)me->mTargetAnim.akeyPositions.size();
nd->mPositionKeys = new aiVectorKey[nd->mNumPositionKeys];

View File

@ -304,7 +304,6 @@ void Parser::Parse() {
}
AI_ASE_HANDLE_TOP_LEVEL_SECTION();
}
return;
}
// ------------------------------------------------------------------------------------------------
@ -734,7 +733,6 @@ void Parser::ParseLV3MapBlock(Texture &map) {
}
AI_ASE_HANDLE_SECTION("3", "*MAP_XXXXXX");
}
return;
}
// ------------------------------------------------------------------------------------------------
@ -859,7 +857,6 @@ void Parser::ParseLV1ObjectBlock(ASE::BaseNode &node) {
}
AI_ASE_HANDLE_TOP_LEVEL_SECTION();
}
return;
}
// ------------------------------------------------------------------------------------------------
@ -883,7 +880,6 @@ void Parser::ParseLV2CameraSettingsBlock(ASE::Camera &camera) {
}
AI_ASE_HANDLE_SECTION("2", "CAMERA_SETTINGS");
}
return;
}
// ------------------------------------------------------------------------------------------------
@ -1189,7 +1185,6 @@ void Parser::ParseLV2NodeTransformBlock(ASE::BaseNode &mesh) {
}
AI_ASE_HANDLE_SECTION("2", "*NODE_TM");
}
return;
}
// ------------------------------------------------------------------------------------------------
void Parser::ParseLV2MeshBlock(ASE::Mesh &mesh) {
@ -1310,7 +1305,6 @@ void Parser::ParseLV2MeshBlock(ASE::Mesh &mesh) {
}
AI_ASE_HANDLE_SECTION("2", "*MESH");
}
return;
}
// ------------------------------------------------------------------------------------------------
void Parser::ParseLV3MeshWeightsBlock(ASE::Mesh &mesh) {
@ -1344,7 +1338,6 @@ void Parser::ParseLV3MeshWeightsBlock(ASE::Mesh &mesh) {
}
AI_ASE_HANDLE_SECTION("3", "*MESH_WEIGHTS");
}
return;
}
// ------------------------------------------------------------------------------------------------
void Parser::ParseLV4MeshBones(unsigned int iNumBones, ASE::Mesh &mesh) {
@ -1414,7 +1407,6 @@ void Parser::ParseLV4MeshBonesVertices(unsigned int iNumVertices, ASE::Mesh &mes
}
AI_ASE_HANDLE_SECTION("4", "*MESH_BONE_VERTEX");
}
return;
}
// ------------------------------------------------------------------------------------------------
void Parser::ParseLV3MeshVertexListBlock(
@ -1443,7 +1435,6 @@ void Parser::ParseLV3MeshVertexListBlock(
}
AI_ASE_HANDLE_SECTION("3", "*MESH_VERTEX_LIST");
}
return;
}
// ------------------------------------------------------------------------------------------------
void Parser::ParseLV3MeshFaceListBlock(unsigned int iNumFaces, ASE::Mesh &mesh) {
@ -1470,7 +1461,6 @@ void Parser::ParseLV3MeshFaceListBlock(unsigned int iNumFaces, ASE::Mesh &mesh)
}
AI_ASE_HANDLE_SECTION("3", "*MESH_FACE_LIST");
}
return;
}
// ------------------------------------------------------------------------------------------------
void Parser::ParseLV3MeshTListBlock(unsigned int iNumVertices,
@ -1503,7 +1493,6 @@ void Parser::ParseLV3MeshTListBlock(unsigned int iNumVertices,
}
AI_ASE_HANDLE_SECTION("3", "*MESH_TVERT_LIST");
}
return;
}
// ------------------------------------------------------------------------------------------------
void Parser::ParseLV3MeshTFaceListBlock(unsigned int iNumFaces,
@ -1532,7 +1521,6 @@ void Parser::ParseLV3MeshTFaceListBlock(unsigned int iNumFaces,
}
AI_ASE_HANDLE_SECTION("3", "*MESH_TFACE_LIST");
}
return;
}
// ------------------------------------------------------------------------------------------------
void Parser::ParseLV3MappingChannel(unsigned int iChannel, ASE::Mesh &mesh) {
@ -1567,7 +1555,6 @@ void Parser::ParseLV3MappingChannel(unsigned int iChannel, ASE::Mesh &mesh) {
}
AI_ASE_HANDLE_SECTION("3", "*MESH_MAPPING_CHANNEL");
}
return;
}
// ------------------------------------------------------------------------------------------------
void Parser::ParseLV3MeshCListBlock(unsigned int iNumVertices, ASE::Mesh &mesh) {
@ -1595,7 +1582,6 @@ void Parser::ParseLV3MeshCListBlock(unsigned int iNumVertices, ASE::Mesh &mesh)
}
AI_ASE_HANDLE_SECTION("3", "*MESH_CVERTEX_LIST");
}
return;
}
// ------------------------------------------------------------------------------------------------
void Parser::ParseLV3MeshCFaceListBlock(unsigned int iNumFaces, ASE::Mesh &mesh) {
@ -1623,7 +1609,6 @@ void Parser::ParseLV3MeshCFaceListBlock(unsigned int iNumFaces, ASE::Mesh &mesh)
}
AI_ASE_HANDLE_SECTION("3", "*MESH_CFACE_LIST");
}
return;
}
// ------------------------------------------------------------------------------------------------
void Parser::ParseLV3MeshNormalListBlock(ASE::Mesh &sMesh) {
@ -1681,7 +1666,6 @@ void Parser::ParseLV3MeshNormalListBlock(ASE::Mesh &sMesh) {
}
AI_ASE_HANDLE_SECTION("3", "*MESH_NORMALS");
}
return;
}
// ------------------------------------------------------------------------------------------------
void Parser::ParseLV4MeshFace(ASE::Face &out) {

View File

@ -7,7 +7,7 @@ For details, see http://sourceforge.net/projects/libb64
#include "cencode.h" // changed from <B64/cencode.h>
const int CHARS_PER_LINE = 72;
static const int CHARS_PER_LINE = 72;
#ifdef _MSC_VER
#pragma warning(push)

View File

@ -96,7 +96,8 @@ struct CustomDataTypeDescription {
* other (like CD_ORCO, ...) uses arrays of rawtypes or even arrays of Structures
* use a special readfunction for that cases
*/
std::array<CustomDataTypeDescription, CD_NUMTYPES> customDataTypeDescriptions = { { DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MVert),
static std::array<CustomDataTypeDescription, CD_NUMTYPES> customDataTypeDescriptions = { {
DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MVert),
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MEdge),

View File

@ -1855,7 +1855,6 @@ size_t ColladaParser::ReadPrimitives(XmlNode &node, Mesh &pMesh, std::vector<Inp
default:
// LineStrip is not supported due to expected index unmangling
throw DeadlyImportError("Unsupported primitive type.");
break;
}
// store the face size to later reconstruct the face from

View File

@ -139,6 +139,7 @@ size_t Offset(const char* begin, const char* cursor) {
}
// ------------------------------------------------------------------------------------------------
AI_WONT_RETURN void TokenizeError(const std::string& message, const char* begin, const char* cursor) AI_WONT_RETURN_SUFFIX;
void TokenizeError(const std::string& message, const char* begin, const char* cursor) {
TokenizeError(message, Offset(begin, cursor));
}
@ -341,8 +342,7 @@ void ReadData(const char*& sbegin_out, const char*& send_out, const char* input,
// ------------------------------------------------------------------------------------------------
bool ReadScope(TokenList& output_tokens, const char* input, const char*& cursor, const char* end, bool const is64bits)
{
bool ReadScope(TokenList &output_tokens, StackAllocator &token_allocator, const char *input, const char *&cursor, const char *end, bool const is64bits) {
// the first word contains the offset at which this block ends
const uint64_t end_offset = is64bits ? ReadDoubleWord(input, cursor, end) : ReadWord(input, cursor, end);
@ -408,7 +408,7 @@ bool ReadScope(TokenList& output_tokens, const char* input, const char*& cursor,
// XXX this is vulnerable to stack overflowing ..
while(Offset(input, cursor) < end_offset - sentinel_block_length) {
ReadScope(output_tokens, input, cursor, input + end_offset - sentinel_block_length, is64bits);
ReadScope(output_tokens, token_allocator, input, cursor, input + end_offset - sentinel_block_length, is64bits);
}
output_tokens.push_back(new_Token(cursor, cursor + 1, TokenType_CLOSE_BRACKET, Offset(input, cursor) ));
@ -431,8 +431,7 @@ bool ReadScope(TokenList& output_tokens, const char* input, const char*& cursor,
// ------------------------------------------------------------------------------------------------
// TODO: Test FBX Binary files newer than the 7500 version to check if the 64 bits address behaviour is consistent
void TokenizeBinary(TokenList& output_tokens, const char* input, size_t length)
{
void TokenizeBinary(TokenList &output_tokens, const char *input, size_t length, StackAllocator &token_allocator) {
ai_assert(input);
ASSIMP_LOG_DEBUG("Tokenizing binary FBX file");
@ -465,7 +464,7 @@ void TokenizeBinary(TokenList& output_tokens, const char* input, size_t length)
try
{
while (cursor < end ) {
if (!ReadScope(output_tokens, input, cursor, input + length, is64bits)) {
if (!ReadScope(output_tokens, token_allocator, input, cursor, input + length, is64bits)) {
break;
}
}

View File

@ -152,7 +152,7 @@ void FBXConverter::ConvertRootNode() {
mSceneOut->mRootNode->mName.Set(unique_name);
// root has ID 0
ConvertNodes(0L, mSceneOut->mRootNode, mSceneOut->mRootNode, aiMatrix4x4());
ConvertNodes(0L, mSceneOut->mRootNode, mSceneOut->mRootNode);
}
static std::string getAncestorBaseName(const aiNode *node) {
@ -196,7 +196,7 @@ struct FBXConverter::PotentialNode {
/// todo: get bone from stack
/// todo: make map of aiBone* to aiNode*
/// then update convert clusters to the new format
void FBXConverter::ConvertNodes(uint64_t id, aiNode *parent, aiNode *root_node, const aiMatrix4x4 &globalTransform) {
void FBXConverter::ConvertNodes(uint64_t id, aiNode *parent, aiNode *root_node) {
const std::vector<const Connection *> &conns = doc.GetConnectionsByDestinationSequenced(id, "Model");
std::vector<PotentialNode> nodes;
@ -290,15 +290,14 @@ void FBXConverter::ConvertNodes(uint64_t id, aiNode *parent, aiNode *root_node,
}
// recursion call - child nodes
aiMatrix4x4 newGlobalMatrix = globalTransform * nodes_chain.front().mNode->mTransformation;
ConvertNodes(model->ID(), last_parent, root_node, newGlobalMatrix);
ConvertNodes(model->ID(), last_parent, root_node);
if (doc.Settings().readLights) {
ConvertLights(*model, node_name);
}
if (doc.Settings().readCameras) {
ConvertCameras(*model, node_name, newGlobalMatrix);
ConvertCameras(*model, node_name);
}
nodes.push_back(std::move(nodes_chain.front()));
@ -328,14 +327,12 @@ void FBXConverter::ConvertLights(const Model &model, const std::string &orig_nam
}
}
void FBXConverter::ConvertCameras(const Model &model,
const std::string &orig_name,
const aiMatrix4x4 &transform) {
void FBXConverter::ConvertCameras(const Model &model, const std::string &orig_name) {
const std::vector<const NodeAttribute *> &node_attrs = model.GetAttributes();
for (const NodeAttribute *attr : node_attrs) {
const Camera *const cam = dynamic_cast<const Camera *>(attr);
if (cam) {
ConvertCamera(*cam, orig_name, transform);
ConvertCamera(*cam, orig_name);
}
}
}
@ -416,9 +413,7 @@ void FBXConverter::ConvertLight(const Light &light, const std::string &orig_name
}
}
void FBXConverter::ConvertCamera(const Camera &cam,
const std::string &orig_name,
aiMatrix4x4 transform) {
void FBXConverter::ConvertCamera(const Camera &cam, const std::string &orig_name) {
cameras.push_back(new aiCamera());
aiCamera *const out_camera = cameras.back();
@ -426,16 +421,11 @@ void FBXConverter::ConvertCamera(const Camera &cam,
out_camera->mAspect = cam.AspectWidth() / cam.AspectHeight();
aiVector3D pos = cam.Position();
out_camera->mLookAt = cam.InterestPosition();
out_camera->mUp = pos + cam.UpVector();
transform.Inverse();
pos *= transform;
out_camera->mLookAt *= transform;
out_camera->mUp *= transform;
out_camera->mLookAt -= pos;
out_camera->mUp -= pos;
// NOTE: Camera mPosition, mLookAt and mUp must be set to default here.
// All transformations to the camera will be handled by its node in the scenegraph.
out_camera->mPosition = aiVector3D(0.0f);
out_camera->mLookAt = aiVector3D(1.0f, 0.0f, 0.0f);
out_camera->mUp = aiVector3D(0.0f, 1.0f, 0.0f);
out_camera->mHorizontalFOV = AI_DEG_TO_RAD(cam.FieldOfView());

View File

@ -134,22 +134,19 @@ private:
// ------------------------------------------------------------------------------------------------
// collect and assign child nodes
void ConvertNodes(uint64_t id, aiNode *parent, aiNode *root_node,
const aiMatrix4x4 &globalTransform);
void ConvertNodes(uint64_t id, aiNode *parent, aiNode *root_node);
// ------------------------------------------------------------------------------------------------
void ConvertLights(const Model& model, const std::string &orig_name );
// ------------------------------------------------------------------------------------------------
void ConvertCameras(const Model& model, const std::string &orig_name,
const aiMatrix4x4 &transform);
void ConvertCameras(const Model& model, const std::string &orig_name );
// ------------------------------------------------------------------------------------------------
void ConvertLight( const Light& light, const std::string &orig_name );
// ------------------------------------------------------------------------------------------------
void ConvertCamera(const Camera& cam, const std::string &orig_name,
aiMatrix4x4 transform);
void ConvertCamera( const Camera& cam, const std::string &orig_name );
// ------------------------------------------------------------------------------------------------
void GetUniqueName( const std::string &name, std::string& uniqueName );

View File

@ -243,7 +243,7 @@ FileGlobalSettings::FileGlobalSettings(const Document &doc, std::shared_ptr<cons
}
// ------------------------------------------------------------------------------------------------
Document::Document(const Parser& parser, const ImportSettings& settings) :
Document::Document(Parser& parser, const ImportSettings& settings) :
settings(settings), parser(parser) {
ASSIMP_LOG_DEBUG("Creating FBX Document");
@ -265,13 +265,17 @@ Document::Document(const Parser& parser, const ImportSettings& settings) :
}
// ------------------------------------------------------------------------------------------------
Document::~Document() {
for(ObjectMap::value_type& v : objects) {
delete v.second;
Document::~Document()
{
// The document does not own the memory for the following objects, but we need to call their d'tor
// so they can properly free memory like string members:
for (ObjectMap::value_type &v : objects) {
delete_LazyObject(v.second);
}
for(ConnectionMap::value_type& v : src_connections) {
delete v.second;
for (ConnectionMap::value_type &v : src_connections) {
delete_Connection(v.second);
}
// |dest_connections| contain the same Connection objects as the |src_connections|
}
@ -356,9 +360,11 @@ void Document::ReadObjects() {
DOMError("no Objects dictionary found");
}
StackAllocator &allocator = parser.GetAllocator();
// add a dummy entry to represent the Model::RootNode object (id 0),
// which is only indirectly defined in the input file
objects[0] = new LazyObject(0L, *eobjects, *this);
objects[0] = new_LazyObject(0L, *eobjects, *this);
const Scope& sobjects = *eobjects->Compound();
for(const ElementMap::value_type& el : sobjects.Elements()) {
@ -387,7 +393,7 @@ void Document::ReadObjects() {
delete foundObject->second;
}
objects[id] = new LazyObject(id, *el.second, *this);
objects[id] = new_LazyObject(id, *el.second, *this);
// grab all animation stacks upfront since there is no listing of them
if(!strcmp(el.first.c_str(),"AnimationStack")) {
@ -454,8 +460,10 @@ void Document::ReadPropertyTemplates() {
}
// ------------------------------------------------------------------------------------------------
void Document::ReadConnections() {
const Scope& sc = parser.GetRootScope();
void Document::ReadConnections()
{
StackAllocator &allocator = parser.GetAllocator();
const Scope &sc = parser.GetRootScope();
// read property templates from "Definitions" section
const Element* const econns = sc["Connections"];
if(!econns || !econns->Compound()) {
@ -494,7 +502,7 @@ void Document::ReadConnections() {
}
// add new connection
const Connection* const c = new Connection(insertionOrder++,src,dest,prop,*this);
const Connection* const c = new_Connection(insertionOrder++,src,dest,prop,*this);
src_connections.insert(ConnectionMap::value_type(src,c));
dest_connections.insert(ConnectionMap::value_type(dest,c));
}

View File

@ -81,6 +81,10 @@ class BlendShape;
class Skin;
class Cluster;
#define new_LazyObject new (allocator.Allocate(sizeof(LazyObject))) LazyObject
#define new_Connection new (allocator.Allocate(sizeof(Connection))) Connection
#define delete_LazyObject(_p) (_p)->~LazyObject()
#define delete_Connection(_p) (_p)->~Connection()
/** Represents a delay-parsed FBX objects. Many objects in the scene
* are not needed by assimp, so it makes no sense to parse them
@ -1073,7 +1077,7 @@ private:
/** DOM root for a FBX file */
class Document {
public:
Document(const Parser& parser, const ImportSettings& settings);
Document(Parser& parser, const ImportSettings& settings);
~Document();
@ -1157,7 +1161,7 @@ private:
const ImportSettings& settings;
ObjectMap objects;
const Parser& parser;
Parser& parser;
PropertyTemplateMap templates;
ConnectionMap src_connections;

View File

@ -152,19 +152,19 @@ void FBXImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
// broad-phase tokenized pass in which we identify the core
// syntax elements of FBX (brackets, commas, key:value mappings)
TokenList tokens;
try {
Assimp::StackAllocator tempAllocator;
try {
bool is_binary = false;
if (!strncmp(begin, "Kaydara FBX Binary", 18)) {
is_binary = true;
TokenizeBinary(tokens, begin, contents.size());
TokenizeBinary(tokens, begin, contents.size(), tempAllocator);
} else {
Tokenize(tokens, begin);
Tokenize(tokens, begin, tempAllocator);
}
// use this information to construct a very rudimentary
// parse-tree representing the FBX scope structure
Parser parser(tokens, is_binary);
Parser parser(tokens, tempAllocator, is_binary);
// take the raw parse-tree and convert it to a FBX DOM
Document doc(parser, mSettings);
@ -183,10 +183,12 @@ void FBXImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
// assimp universal format (M)
SetFileScale(size_relative_to_cm * 0.01f);
std::for_each(tokens.begin(), tokens.end(), Util::delete_fun<Token>());
} catch (std::exception &) {
std::for_each(tokens.begin(), tokens.end(), Util::delete_fun<Token>());
throw;
// This collection does not own the memory for the tokens, but we need to call their d'tor
std::for_each(tokens.begin(), tokens.end(), Util::destructor_fun<Token>());
} catch (std::exception &) {
std::for_each(tokens.begin(), tokens.end(), Util::destructor_fun<Token>());
throw;
}
}

View File

@ -138,20 +138,6 @@ Material::Material(uint64_t id, const Element& element, const Document& doc, con
// ------------------------------------------------------------------------------------------------
Material::~Material() = default;
aiVector2D uvTrans;
aiVector2D uvScaling;
ai_real uvRotation;
std::string type;
std::string relativeFileName;
std::string fileName;
std::string alphaSource;
std::shared_ptr<const PropertyTable> props;
unsigned int crop[4]{};
const Video* media;
// ------------------------------------------------------------------------------------------------
Texture::Texture(uint64_t id, const Element& element, const Document& doc, const std::string& name) :
Object(id,element,name),

View File

@ -88,6 +88,7 @@ namespace {
// ------------------------------------------------------------------------------------------------
AI_WONT_RETURN void ParseError(const std::string& message, TokenPtr token) AI_WONT_RETURN_SUFFIX;
void ParseError(const std::string& message, TokenPtr token)
{
if(token) {
@ -115,8 +116,11 @@ namespace Assimp {
namespace FBX {
// ------------------------------------------------------------------------------------------------
Element::Element(const Token& key_token, Parser& parser) : key_token(key_token) {
Element::Element(const Token& key_token, Parser& parser) :
key_token(key_token), compound(nullptr)
{
TokenPtr n = nullptr;
StackAllocator &allocator = parser.GetAllocator();
do {
n = parser.AdvanceToNextToken();
if(!n) {
@ -145,7 +149,7 @@ Element::Element(const Token& key_token, Parser& parser) : key_token(key_token)
}
if (n->Type() == TokenType_OPEN_BRACKET) {
compound.reset(new Scope(parser));
compound = new_Scope(parser);
// current token should be a TOK_CLOSE_BRACKET
n = parser.CurrentToken();
@ -163,6 +167,15 @@ Element::Element(const Token& key_token, Parser& parser) : key_token(key_token)
}
// ------------------------------------------------------------------------------------------------
Element::~Element()
{
if (compound) {
delete_Scope(compound);
}
// no need to delete tokens, they are owned by the parser
}
Scope::Scope(Parser& parser,bool topLevel)
{
if(!topLevel) {
@ -172,6 +185,7 @@ Scope::Scope(Parser& parser,bool topLevel)
}
}
StackAllocator &allocator = parser.GetAllocator();
TokenPtr n = parser.AdvanceToNextToken();
if (n == nullptr) {
ParseError("unexpected end of file");
@ -188,36 +202,45 @@ Scope::Scope(Parser& parser,bool topLevel)
ParseError("unexpected content: empty string.");
}
elements.insert(ElementMap::value_type(str,new_Element(*n,parser)));
auto *element = new_Element(*n, parser);
// Element() should stop at the next Key token (or right after a Close token)
n = parser.CurrentToken();
if (n == nullptr) {
if (topLevel) {
elements.insert(ElementMap::value_type(str, element));
return;
}
delete element;
ParseError("unexpected end of file",parser.LastToken());
} else {
elements.insert(ElementMap::value_type(str, element));
}
}
}
// ------------------------------------------------------------------------------------------------
Scope::~Scope() {
for(ElementMap::value_type& v : elements) {
delete v.second;
Scope::~Scope()
{
// This collection does not own the memory for the elements, but we need to call their d'tor:
for (ElementMap::value_type &v : elements) {
delete_Element(v.second);
}
}
// ------------------------------------------------------------------------------------------------
Parser::Parser (const TokenList& tokens, bool is_binary)
: tokens(tokens)
, last()
, current()
, cursor(tokens.begin())
, is_binary(is_binary)
Parser::Parser(const TokenList &tokens, StackAllocator &allocator, bool is_binary) :
tokens(tokens), allocator(allocator), last(), current(), cursor(tokens.begin()), is_binary(is_binary)
{
ASSIMP_LOG_DEBUG("Parsing FBX tokens");
root.reset(new Scope(*this,true));
root = new_Scope(*this, true);
}
// ------------------------------------------------------------------------------------------------
Parser::~Parser()
{
delete_Scope(root);
}
// ------------------------------------------------------------------------------------------------

View File

@ -52,6 +52,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/LogAux.h>
#include <assimp/fast_atof.h>
#include "Common/StackAllocator.h"
#include "FBXCompileConfig.h"
#include "FBXTokenizer.h"
@ -63,14 +64,14 @@ class Parser;
class Element;
// XXX should use C++11's unique_ptr - but assimp's need to keep working with 03
typedef std::vector< Scope* > ScopeList;
typedef std::fbx_unordered_multimap< std::string, Element* > ElementMap;
typedef std::pair<ElementMap::const_iterator,ElementMap::const_iterator> ElementCollection;
# define new_Scope new Scope
# define new_Element new Element
using ScopeList = std::vector<Scope*>;
using ElementMap = std::fbx_unordered_multimap< std::string, Element*>;
using ElementCollection = std::pair<ElementMap::const_iterator,ElementMap::const_iterator>;
#define new_Scope new (allocator.Allocate(sizeof(Scope))) Scope
#define new_Element new (allocator.Allocate(sizeof(Element))) Element
#define delete_Scope(_p) (_p)->~Scope()
#define delete_Element(_p) (_p)->~Element()
/** FBX data entity that consists of a key:value tuple.
*
@ -82,15 +83,16 @@ typedef std::pair<ElementMap::const_iterator,ElementMap::const_iterator> Element
* @endverbatim
*
* As can be seen in this sample, elements can contain nested #Scope
* as their trailing member. **/
* as their trailing member.
**/
class Element
{
public:
Element(const Token& key_token, Parser& parser);
~Element() = default;
~Element();
const Scope* Compound() const {
return compound.get();
return compound;
}
const Token& KeyToken() const {
@ -104,7 +106,7 @@ public:
private:
const Token& key_token;
TokenList tokens;
std::unique_ptr<Scope> compound;
Scope* compound;
};
/** FBX data entity that consists of a 'scope', a collection
@ -159,8 +161,8 @@ class Parser
public:
/** Parse given a token list. Does not take ownership of the tokens -
* the objects must persist during the entire parser lifetime */
Parser (const TokenList& tokens,bool is_binary);
~Parser() = default;
Parser(const TokenList &tokens, StackAllocator &allocator, bool is_binary);
~Parser();
const Scope& GetRootScope() const {
return *root;
@ -170,6 +172,10 @@ public:
return is_binary;
}
StackAllocator &GetAllocator() {
return allocator;
}
private:
friend class Scope;
friend class Element;
@ -180,10 +186,10 @@ private:
private:
const TokenList& tokens;
StackAllocator &allocator;
TokenPtr last, current;
TokenList::const_iterator cursor;
std::unique_ptr<Scope> root;
Scope *root;
const bool is_binary;
};

View File

@ -94,7 +94,8 @@ AI_WONT_RETURN void TokenizeError(const std::string& message, unsigned int line,
// process a potential data token up to 'cur', adding it to 'output_tokens'.
// ------------------------------------------------------------------------------------------------
void ProcessDataToken( TokenList& output_tokens, const char*& start, const char*& end,
void ProcessDataToken(TokenList &output_tokens, StackAllocator &token_allocator,
const char*& start, const char*& end,
unsigned int line,
unsigned int column,
TokenType type = TokenType_DATA,
@ -131,8 +132,7 @@ void ProcessDataToken( TokenList& output_tokens, const char*& start, const char*
}
// ------------------------------------------------------------------------------------------------
void Tokenize(TokenList& output_tokens, const char* input)
{
void Tokenize(TokenList &output_tokens, const char *input, StackAllocator &token_allocator) {
ai_assert(input);
ASSIMP_LOG_DEBUG("Tokenizing ASCII FBX file");
@ -164,7 +164,7 @@ void Tokenize(TokenList& output_tokens, const char* input)
in_double_quotes = false;
token_end = cur;
ProcessDataToken(output_tokens,token_begin,token_end,line,column);
ProcessDataToken(output_tokens, token_allocator, token_begin, token_end, line, column);
pending_data_token = false;
}
continue;
@ -181,30 +181,30 @@ void Tokenize(TokenList& output_tokens, const char* input)
continue;
case ';':
ProcessDataToken(output_tokens,token_begin,token_end,line,column);
ProcessDataToken(output_tokens, token_allocator, token_begin, token_end, line, column);
comment = true;
continue;
case '{':
ProcessDataToken(output_tokens,token_begin,token_end, line, column);
ProcessDataToken(output_tokens, token_allocator, token_begin, token_end, line, column);
output_tokens.push_back(new_Token(cur,cur+1,TokenType_OPEN_BRACKET,line,column));
continue;
case '}':
ProcessDataToken(output_tokens,token_begin,token_end,line,column);
ProcessDataToken(output_tokens, token_allocator, token_begin, token_end, line, column);
output_tokens.push_back(new_Token(cur,cur+1,TokenType_CLOSE_BRACKET,line,column));
continue;
case ',':
if (pending_data_token) {
ProcessDataToken(output_tokens,token_begin,token_end,line,column,TokenType_DATA,true);
ProcessDataToken(output_tokens, token_allocator, token_begin, token_end, line, column, TokenType_DATA, true);
}
output_tokens.push_back(new_Token(cur,cur+1,TokenType_COMMA,line,column));
continue;
case ':':
if (pending_data_token) {
ProcessDataToken(output_tokens,token_begin,token_end,line,column,TokenType_KEY,true);
ProcessDataToken(output_tokens, token_allocator, token_begin, token_end, line, column, TokenType_KEY, true);
}
else {
TokenizeError("unexpected colon", line, column);
@ -226,7 +226,7 @@ void Tokenize(TokenList& output_tokens, const char* input)
}
}
ProcessDataToken(output_tokens,token_begin,token_end,line,column,type);
ProcessDataToken(output_tokens, token_allocator, token_begin, token_end, line, column, type);
}
pending_data_token = false;

View File

@ -47,6 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define INCLUDED_AI_FBX_TOKENIZER_H
#include "FBXCompileConfig.h"
#include "Common/StackAllocator.h"
#include <assimp/ai_assert.h>
#include <assimp/defs.h>
#include <vector>
@ -157,7 +158,8 @@ private:
typedef const Token* TokenPtr;
typedef std::vector< TokenPtr > TokenList;
#define new_Token new Token
#define new_Token new (token_allocator.Allocate(sizeof(Token))) Token
#define delete_Token(_p) (_p)->~Token()
/** Main FBX tokenizer function. Transform input buffer into a list of preprocessed tokens.
@ -167,7 +169,7 @@ typedef std::vector< TokenPtr > TokenList;
* @param output_tokens Receives a list of all tokens in the input data.
* @param input_buffer Textual input buffer to be processed, 0-terminated.
* @throw DeadlyImportError if something goes wrong */
void Tokenize(TokenList& output_tokens, const char* input);
void Tokenize(TokenList &output_tokens, const char *input, StackAllocator &tokenAllocator);
/** Tokenizer function for binary FBX files.
@ -178,7 +180,7 @@ void Tokenize(TokenList& output_tokens, const char* input);
* @param input_buffer Binary input buffer to be processed.
* @param length Length of input buffer, in bytes. There is no 0-terminal.
* @throw DeadlyImportError if something goes wrong */
void TokenizeBinary(TokenList& output_tokens, const char* input, size_t length);
void TokenizeBinary(TokenList &output_tokens, const char *input, size_t length, StackAllocator &tokenAllocator);
} // ! FBX

View File

@ -66,6 +66,17 @@ struct delete_fun
}
};
/** helper for std::for_each to call the destructor on all items in a container without freeing their heap*/
template <typename T>
struct destructor_fun {
void operator()(const volatile T* del) {
if (del) {
del->~T();
}
}
};
/** Get a string representation for a #TokenType. */
const char* TokenTypeString(TokenType t);

View File

@ -86,7 +86,7 @@ protected:
// -------------------------------------------------------------------
/** Import a HMP4 file
*/
void InternReadFile_HMP4();
AI_WONT_RETURN void InternReadFile_HMP4() AI_WONT_RETURN_SUFFIX;
// -------------------------------------------------------------------
/** Import a HMP5 file

View File

@ -48,6 +48,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "AssetLib/IFC/IFCUtil.h"
#include "Common/PolyTools.h"
#include "Geometry/GeometryUtils.h"
#include "PostProcessing/ProcessHelper.h"
namespace Assimp {
@ -235,7 +236,7 @@ IfcVector3 TempMesh::ComputeLastPolygonNormal(bool normalize) const {
struct CompareVector {
bool operator () (const IfcVector3& a, const IfcVector3& b) const {
IfcVector3 d = a - b;
IfcFloat eps = ai_epsilon;
constexpr IfcFloat eps = ai_epsilon;
return d.x < -eps || (std::abs(d.x) < eps && d.y < -eps) || (std::abs(d.x) < eps && std::abs(d.y) < eps && d.z < -eps);
}
};

View File

@ -65,7 +65,6 @@ void LWOImporter::LoadLWOBFile()
if (mFileBuffer + head.length > end)
{
throw DeadlyImportError("LWOB: Invalid chunk length");
break;
}
uint8_t* const next = mFileBuffer+head.length;
switch (head.type)

View File

@ -5,8 +5,6 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2022, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
@ -51,6 +49,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "AssetLib/LWO/LWOLoader.h"
#include "PostProcessing/ConvertToLHProcess.h"
#include "PostProcessing/ProcessHelper.h"
#include "Geometry/GeometryUtils.h"
#include <assimp/ByteSwapper.h>
#include <assimp/SGSpatialSort.h>
@ -528,7 +527,6 @@ void LWOImporter::ComputeNormals(aiMesh *mesh, const std::vector<unsigned int> &
continue;
vNormals += v;
}
mesh->mNormals[idx] = vNormals.Normalize();
}
}
}
@ -549,7 +547,6 @@ void LWOImporter::ComputeNormals(aiMesh *mesh, const std::vector<unsigned int> &
const aiVector3D &v = faceNormals[*a];
vNormals += v;
}
vNormals.Normalize();
for (std::vector<unsigned int>::const_iterator a = poResult.begin(); a != poResult.end(); ++a) {
mesh->mNormals[*a] = vNormals;
vertexDone[*a] = true;
@ -557,6 +554,7 @@ void LWOImporter::ComputeNormals(aiMesh *mesh, const std::vector<unsigned int> &
}
}
}
GeometryUtils::normalizeVectorArray(mesh->mNormals, mesh->mNormals, mesh->mNumVertices);
}
// ------------------------------------------------------------------------------------------------
@ -1486,7 +1484,6 @@ void LWOImporter::LoadLWO2File() {
if (mFileBuffer + head.length > end) {
throw DeadlyImportError("LWO2: Chunk length points behind the file");
break;
}
uint8_t *const next = mFileBuffer + head.length;
mFileBuffer += bufOffset;

View File

@ -365,9 +365,7 @@ public:
static void ReportWarning (const char* warn, unsigned int line);
void ReportError (const char* error) {
return ReportError(error, lineNumber);
}
AI_WONT_RETURN void ReportError (const char* error) AI_WONT_RETURN_SUFFIX;
void ReportWarning (const char* warn) {
return ReportWarning(warn, lineNumber);
@ -404,6 +402,9 @@ private:
unsigned int lineNumber;
};
inline void MD5Parser::ReportError(const char* error) {
ReportError(error, lineNumber);
}
// -------------------------------------------------------------------
inline bool MD5Parser::SkipLine(const char* in, const char** out) {
++lineNumber;

View File

@ -139,7 +139,7 @@ protected:
// -------------------------------------------------------------------
/** Import a CS:S/HL2 MDL file (not fully implemented)
*/
void InternReadFile_HL2( );
AI_WONT_RETURN void InternReadFile_HL2( ) AI_WONT_RETURN_SUFFIX;
// -------------------------------------------------------------------
/** Check whether a given position is inside the valid range

View File

@ -46,6 +46,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <iostream>
#include <fstream>
#include <memory>
#include <assimp/types.h>
#include "MMDCpp14.h"
namespace pmx
@ -730,7 +731,7 @@ namespace pmx
std::unique_ptr<PmxAncherRigidBody []> anchers;
int pin_vertex_count;
std::unique_ptr<int []> pin_vertices;
void Read(std::istream *stream, PmxSetting *setting);
AI_WONT_RETURN void Read(std::istream *stream, PmxSetting *setting) AI_WONT_RETURN_SUFFIX;
};
class PmxModel

View File

@ -3,7 +3,7 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team
Copyright (c) 2006-2023, assimp team
All rights reserved.
@ -84,7 +84,6 @@ ObjFileImporter::ObjFileImporter() :
// Destructor.
ObjFileImporter::~ObjFileImporter() {
delete m_pRootObject;
m_pRootObject = nullptr;
}
// ------------------------------------------------------------------------------------------------
@ -270,7 +269,7 @@ aiNode *ObjFileImporter::createNodes(const ObjFile::Model *pModel, const ObjFile
for (size_t i = 0; i < pObject->m_Meshes.size(); ++i) {
unsigned int meshId = pObject->m_Meshes[i];
aiMesh *pMesh = createTopology(pModel, pObject, meshId);
if (pMesh) {
if (pMesh != nullptr) {
if (pMesh->mNumFaces > 0) {
MeshArray.push_back(pMesh);
} else {
@ -324,14 +323,13 @@ aiMesh *ObjFileImporter::createTopology(const ObjFile::Model *pModel, const ObjF
return nullptr;
}
std::unique_ptr<aiMesh> pMesh(new aiMesh);
aiMesh *pMesh = new aiMesh;
if (!pObjMesh->m_name.empty()) {
pMesh->mName.Set(pObjMesh->m_name);
}
for (size_t index = 0; index < pObjMesh->m_Faces.size(); index++) {
const ObjFile::Face *inp = pObjMesh->m_Faces[index];
//ai_assert(nullptr != inp);
if (inp->mPrimitiveType == aiPrimitiveType_LINE) {
pMesh->mNumFaces += static_cast<unsigned int>(inp->m_vertices.size() - 1);
@ -387,9 +385,9 @@ aiMesh *ObjFileImporter::createTopology(const ObjFile::Model *pModel, const ObjF
}
// Create mesh vertices
createVertexArray(pModel, pData, meshIndex, pMesh.get(), uiIdxCount);
createVertexArray(pModel, pData, meshIndex, pMesh, uiIdxCount);
return pMesh.release();
return pMesh;
}
// ------------------------------------------------------------------------------------------------

View File

@ -236,7 +236,7 @@ void ObjFileParser::parseFile(IOStreamBuffer<char> &streamBuffer) {
getNameNoSpace(m_DataIt, m_DataItEnd, name);
insideCstype = name == "cstype";
goto pf_skip_line;
} break;
}
default: {
pf_skip_line:

View File

@ -57,7 +57,7 @@ namespace Assimp {
namespace Ogre {
//AI_WONT_RETURN void ThrowAttibuteError(const XmlParser *reader, const std::string &name, const std::string &error = "") AI_WONT_RETURN_SUFFIX;
AI_WONT_RETURN void ThrowAttibuteError(const std::string &nodeName, const std::string &name, const std::string &error) AI_WONT_RETURN_SUFFIX;
AI_WONT_RETURN void ThrowAttibuteError(const std::string &nodeName, const std::string &name, const std::string &error) {
if (!error.empty()) {
throw DeadlyImportError(error, " in node '", nodeName, "' and attribute '", name, "'");
@ -128,7 +128,6 @@ bool OgreXmlSerializer::ReadAttribute<bool>(XmlNode &xmlNode, const char *name)
}
ThrowAttibuteError(xmlNode.name(), name, "Boolean value is expected to be 'true' or 'false', encountered '" + value + "'");
return false;
}
// Mesh XML constants

View File

@ -460,14 +460,12 @@ void OpenGEXImporter::handleMetricNode(DDLNode *node, aiScene * /*pScene*/) {
void OpenGEXImporter::handleNameNode(DDLNode *node, aiScene * /*pScene*/) {
if (nullptr == m_currentNode) {
throw DeadlyImportError("No current node for name.");
return;
}
Value *val(node->getValue());
if (nullptr != val) {
if (Value::ValueType::ddl_string != val->m_type) {
throw DeadlyImportError("OpenGEX: invalid data type for value in node name.");
return;
}
const std::string name(val->getString());
@ -508,7 +506,6 @@ static void getRefNames(DDLNode *node, std::vector<std::string> &names) {
void OpenGEXImporter::handleObjectRefNode(DDLNode *node, aiScene * /*pScene*/) {
if (nullptr == m_currentNode) {
throw DeadlyImportError("No parent node for name.");
return;
}
std::vector<std::string> objRefNames;
@ -532,7 +529,6 @@ void OpenGEXImporter::handleObjectRefNode(DDLNode *node, aiScene * /*pScene*/) {
void OpenGEXImporter::handleMaterialRefNode(ODDLParser::DDLNode *node, aiScene * /*pScene*/) {
if (nullptr == m_currentNode) {
throw DeadlyImportError("No parent node for name.");
return;
}
std::vector<std::string> matRefNames;
@ -672,14 +668,12 @@ static void setMatrix(aiNode *node, DataArrayList *transformData) {
void OpenGEXImporter::handleTransformNode(ODDLParser::DDLNode *node, aiScene * /*pScene*/) {
if (nullptr == m_currentNode) {
throw DeadlyImportError("No parent node for name.");
return;
}
DataArrayList *transformData(node->getDataArrayList());
if (nullptr != transformData) {
if (transformData->m_numItems != 16) {
throw DeadlyImportError("Invalid number of data for transform matrix.");
return;
}
setMatrix(m_currentNode, transformData);
}
@ -835,7 +829,6 @@ static void copyColor4DArray(size_t numItems, DataArrayList *vaList, aiColor4D *
void OpenGEXImporter::handleVertexArrayNode(ODDLParser::DDLNode *node, aiScene * /*pScene*/) {
if (nullptr == node) {
throw DeadlyImportError("No parent node for name.");
return;
}
Property *prop = node->getProperties();
@ -876,12 +869,10 @@ void OpenGEXImporter::handleVertexArrayNode(ODDLParser::DDLNode *node, aiScene *
void OpenGEXImporter::handleIndexArrayNode(ODDLParser::DDLNode *node, aiScene * /*pScene*/) {
if (nullptr == node) {
throw DeadlyImportError("No parent node for name.");
return;
}
if (nullptr == m_currentMesh) {
throw DeadlyImportError("No current mesh for index data found.");
return;
}
DataArrayList *vaList = node->getDataArrayList();

View File

@ -382,11 +382,10 @@ void Q3DImporter::InternReadFile(const std::string &pFile,
// TODO
goto outer;
} break;
}
default:
throw DeadlyImportError("Quick3D: Unknown chunk");
break;
};
}
outer:

View File

@ -58,7 +58,7 @@ namespace Assimp {
class RAWImporter : public BaseImporter {
public:
RAWImporter();
~RAWImporter();
~RAWImporter() override;
// -------------------------------------------------------------------
/** Returns whether the class can handle the format of the given file.

View File

@ -85,7 +85,7 @@ static const aiImporterDesc desc = {
struct SIBChunk {
uint32_t Tag;
uint32_t Size;
} PACK_STRUCT;
};
enum {
POS,

View File

@ -56,7 +56,7 @@ namespace Assimp {
class UnrealImporter : public BaseImporter {
public:
UnrealImporter();
~UnrealImporter();
~UnrealImporter() override;
// -------------------------------------------------------------------
/** @brief Returns whether we can handle the format of the given file

View File

@ -578,7 +578,7 @@ void XFileImporter::ConvertMaterials( aiScene* pScene, std::vector<XFile::Materi
aiString name;
pScene->mMaterials[b]->Get( AI_MATKEY_NAME, name);
if( strcmp( name.C_Str(), oldMat.mName.data()) == 0 ) {
oldMat.sceneIndex = a;
oldMat.sceneIndex = b;
break;
}
}

View File

@ -839,7 +839,6 @@ void XFileParser::ParseDataObjectAnimationKey(AnimBone *pAnimBone) {
default:
ThrowException("Unknown key type ", keyType, " in animation.");
break;
} // end switch
// key separator

View File

@ -58,8 +58,6 @@ class X3DExporter {
Value(value) {
// empty
}
SAttribute(SAttribute &&rhs) AI_NO_EXCEPT = default;
};
/***********************************************/

View File

@ -55,6 +55,18 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <string>
namespace Assimp {
AI_WONT_RETURN inline void Throw_ArgOutOfRange(const std::string &argument) AI_WONT_RETURN_SUFFIX;
AI_WONT_RETURN inline void Throw_CloseNotFound(const std::string &node) AI_WONT_RETURN_SUFFIX;
AI_WONT_RETURN inline void Throw_ConvertFail_Str2ArrF(const std::string &nodeName, const std::string &pAttrValue) AI_WONT_RETURN_SUFFIX;
AI_WONT_RETURN inline void Throw_ConvertFail_Str2ArrD(const std::string &nodeName, const std::string &pAttrValue) AI_WONT_RETURN_SUFFIX;
AI_WONT_RETURN inline void Throw_ConvertFail_Str2ArrB(const std::string &nodeName, const std::string &pAttrValue) AI_WONT_RETURN_SUFFIX;
AI_WONT_RETURN inline void Throw_ConvertFail_Str2ArrI(const std::string &nodeName, const std::string &pAttrValue) AI_WONT_RETURN_SUFFIX;
AI_WONT_RETURN inline void Throw_DEF_And_USE(const std::string &nodeName) AI_WONT_RETURN_SUFFIX;
AI_WONT_RETURN inline void Throw_IncorrectAttr(const std::string &nodeName, const std::string &pAttrName) AI_WONT_RETURN_SUFFIX;
AI_WONT_RETURN inline void Throw_IncorrectAttrValue(const std::string &nodeName, const std::string &pAttrName) AI_WONT_RETURN_SUFFIX;
AI_WONT_RETURN inline void Throw_MoreThanOnceDefined(const std::string &nodeName, const std::string &pNodeType, const std::string &pDescription) AI_WONT_RETURN_SUFFIX;
AI_WONT_RETURN inline void Throw_TagCountIncorrect(const std::string &pNode) AI_WONT_RETURN_SUFFIX;
AI_WONT_RETURN inline void Throw_USE_NotFound(const std::string &nodeName, const std::string &pAttrValue) AI_WONT_RETURN_SUFFIX;
inline void Throw_ArgOutOfRange(const std::string &argument) {
throw DeadlyImportError("Argument value is out of range for: \"" + argument + "\".");

View File

@ -12,7 +12,6 @@ bool X3DXmlHelper::getColor3DAttribute(XmlNode &node, const char *attributeName,
tokenize<std::string>(val, values, " ");
if (values.size() != 3) {
Throw_ConvertFail_Str2ArrF(node.name(), attributeName);
return false;
}
auto it = values.begin();
color.r = stof(*it++);
@ -30,7 +29,6 @@ bool X3DXmlHelper::getVector2DAttribute(XmlNode &node, const char *attributeName
tokenize<std::string>(val, values, " ");
if (values.size() != 2) {
Throw_ConvertFail_Str2ArrF(node.name(), attributeName);
return false;
}
auto it = values.begin();
color.x = stof(*it++);
@ -47,7 +45,6 @@ bool X3DXmlHelper::getVector3DAttribute(XmlNode &node, const char *attributeName
tokenize<std::string>(val, values, " ");
if (values.size() != 3) {
Throw_ConvertFail_Str2ArrF(node.name(), attributeName);
return false;
}
auto it = values.begin();
color.x = stof(*it++);

View File

@ -484,7 +484,7 @@ private:
public:
Buffer();
~Buffer();
~Buffer() override;
void Read(Value &obj, Asset &r);

View File

@ -194,6 +194,8 @@ SET( Common_SRCS
Common/ScenePreprocessor.cpp
Common/ScenePreprocessor.h
Common/SkeletonMeshBuilder.cpp
Common/StackAllocator.h
Common/StackAllocator.inl
Common/StandardShapes.cpp
Common/TargetAnimation.cpp
Common/TargetAnimation.h
@ -1211,7 +1213,6 @@ IF (ASSIMP_WARNINGS_AS_ERRORS)
-Wno-undef
-Wno-suggest-destructor-override
-Wno-suggest-override
-Wno-inconsistent-missing-destructor-override
-Wno-zero-as-null-pointer-constant
-Wno-global-constructors
-Wno-exit-time-destructors
@ -1235,19 +1236,14 @@ IF (ASSIMP_WARNINGS_AS_ERRORS)
-Wno-header-hygiene
-Wno-tautological-value-range-compare
-Wno-tautological-type-limit-compare
-Wno-missing-noreturn
-Wno-missing-variable-declarations
-Wno-extra-semi
-Wno-nonportable-system-include-path
-Wno-undefined-reinterpret-cast
-Wno-shift-sign-overflow
-Wno-deprecated-copy-with-user-provided-dtor
-Wno-deprecated-copy-with-dtor
-Wno-deprecated
-Wno-format-nonliteral
-Wno-comma
-Wno-unreachable-code-break
-Wno-unreachable-code-return
-Wno-implicit-fallthrough
-Wno-unused-template
-Wno-undefined-func-template

View File

@ -1349,6 +1349,9 @@ void SceneCombiner::Copy(aiMetadata **_dest, const aiMetadata *src) {
case AI_AIVECTOR3D:
out.mData = new aiVector3D(*static_cast<aiVector3D *>(in.mData));
break;
case AI_AIMETADATA:
out.mData = new aiMetadata(*static_cast<aiMetadata *>(in.mData));
break;
default:
ai_assert(false);
break;

View File

@ -0,0 +1,92 @@
/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2022, 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 StackAllocator.h
* @brief A very bare-bone allocator class that is suitable when
* allocating many small objects, e.g. during parsing.
* Individual objects are not freed, instead only the whole memory
* can be deallocated.
*/
#ifndef AI_STACK_ALLOCATOR_H_INC
#define AI_STACK_ALLOCATOR_H_INC
#include <vector>
#include <stdint.h>
#include <stddef.h>
namespace Assimp {
/** @brief A very bare-bone allocator class that is suitable when
* allocating many small objects, e.g. during parsing.
* Individual objects are not freed, instead only the whole memory
* can be deallocated.
*/
class StackAllocator {
public:
/// @brief Constructs the allocator
inline StackAllocator();
/// @brief Destructs the allocator and frees all memory
inline ~StackAllocator();
// non copyable
StackAllocator(const StackAllocator &) = delete;
StackAllocator &operator=(const StackAllocator &) = delete;
/// @brief Returns a pointer to byteSize bytes of heap memory that persists
/// for the lifetime of the allocator (or until FreeAll is called).
inline void *Allocate(size_t byteSize);
/// @brief Releases all the memory owned by this allocator.
// Memory provided through function Allocate is not valid anymore after this function has been called.
inline void FreeAll();
private:
constexpr const static size_t g_maxBytesPerBlock = 64 * 1024 * 1024; // The maximum size (in bytes) of a block
constexpr const static size_t g_startBytesPerBlock = 16 * 1024; // Size of the first block. Next blocks will double in size until maximum size of g_maxBytesPerBlock
size_t m_blockAllocationSize = g_startBytesPerBlock; // Block size of the current block
size_t m_subIndex = g_maxBytesPerBlock; // The current byte offset in the current block
std::vector<uint8_t *> m_storageBlocks; // A list of blocks
};
} // namespace Assimp
#include "StackAllocator.inl"
#endif // include guard

View File

@ -0,0 +1,82 @@
/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2022, 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.
----------------------------------------------------------------------
*/
#include "StackAllocator.h"
#include <assimp/ai_assert.h>
using namespace Assimp;
inline StackAllocator::StackAllocator() {
}
inline StackAllocator::~StackAllocator() {
FreeAll();
}
inline void *StackAllocator::Allocate(size_t byteSize) {
if (m_subIndex + byteSize > m_blockAllocationSize) // start a new block
{
// double block size every time, up to maximum of g_maxBytesPerBlock.
// Block size must be at least as large as byteSize, but we want to use this for small allocations anyway.
m_blockAllocationSize = std::max(std::min(m_blockAllocationSize * 2, g_maxBytesPerBlock), byteSize);
uint8_t *data = new uint8_t[m_blockAllocationSize];
m_storageBlocks.emplace_back(data);
m_subIndex = byteSize;
return data;
}
uint8_t *data = m_storageBlocks.back();
data += m_subIndex;
m_subIndex += byteSize;
return data;
}
inline void StackAllocator::FreeAll() {
for (size_t i = 0; i < m_storageBlocks.size(); i++) {
delete [] m_storageBlocks[i];
}
std::vector<uint8_t *> empty;
m_storageBlocks.swap(empty);
// start over:
m_blockAllocationSize = g_startBytesPerBlock;
m_subIndex = g_maxBytesPerBlock;
}

View File

@ -68,7 +68,7 @@ class ZipFile : public IOStream {
public:
std::string m_Filename;
virtual ~ZipFile();
virtual ~ZipFile() override;
// IOStream interface
size_t Read(void *pvBuffer, size_t pSize, size_t pCount) override;

View File

@ -45,35 +45,59 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace Assimp {
// ------------------------------------------------------------------------------------------------
ai_real GeometryUtils::heron( ai_real a, ai_real b, ai_real c ) {
ai_real s = (a + b + c) / 2;
ai_real area = pow((s * ( s - a ) * ( s - b ) * ( s - c ) ), (ai_real)0.5 );
const ai_real s = (a + b + c) / 2;
const ai_real area = pow((s * ( s - a ) * ( s - b ) * ( s - c ) ), (ai_real)0.5 );
return area;
}
ai_real GeometryUtils::distance3D( const aiVector3D &vA, aiVector3D &vB ) {
// ------------------------------------------------------------------------------------------------
ai_real GeometryUtils::distance3D( const aiVector3D &vA, const aiVector3D &vB ) {
const ai_real lx = ( vB.x - vA.x );
const ai_real ly = ( vB.y - vA.y );
const ai_real lz = ( vB.z - vA.z );
ai_real a = lx*lx + ly*ly + lz*lz;
ai_real d = pow( a, (ai_real)0.5 );
const ai_real a = lx*lx + ly*ly + lz*lz;
const ai_real d = pow( a, (ai_real)0.5 );
return d;
}
// ------------------------------------------------------------------------------------------------
ai_real GeometryUtils::calculateAreaOfTriangle( const aiFace& face, aiMesh* mesh ) {
ai_real area = 0;
aiVector3D vA( mesh->mVertices[ face.mIndices[ 0 ] ] );
aiVector3D vB( mesh->mVertices[ face.mIndices[ 1 ] ] );
aiVector3D vC( mesh->mVertices[ face.mIndices[ 2 ] ] );
const aiVector3D vA( mesh->mVertices[ face.mIndices[ 0 ] ] );
const aiVector3D vB( mesh->mVertices[ face.mIndices[ 1 ] ] );
const aiVector3D vC( mesh->mVertices[ face.mIndices[ 2 ] ] );
ai_real a( distance3D( vA, vB ) );
ai_real b( distance3D( vB, vC ) );
ai_real c( distance3D( vC, vA ) );
const ai_real a = distance3D( vA, vB );
const ai_real b = distance3D( vB, vC );
const ai_real c = distance3D( vC, vA );
area = heron( a, b, c );
return area;
}
// ------------------------------------------------------------------------------------------------
// Check whether a ray intersects a plane and find the intersection point
bool GeometryUtils::PlaneIntersect(const aiRay& ray, const aiVector3D& planePos,
const aiVector3D& planeNormal, aiVector3D& pos) {
const ai_real b = planeNormal * (planePos - ray.pos);
ai_real h = ray.dir * planeNormal;
if ((h < 10e-5 && h > -10e-5) || (h = b/h) < 0)
return false;
pos = ray.pos + (ray.dir * h);
return true;
}
// ------------------------------------------------------------------------------------------------
void GeometryUtils::normalizeVectorArray(aiVector3D *vectorArrayIn, aiVector3D *vectorArrayOut,
size_t numVectors) {
for (size_t i=0; i<numVectors; ++i) {
vectorArrayOut[i] = vectorArrayIn[i].Normalize();
}
}
} // namespace Assimp

View File

@ -47,7 +47,7 @@ namespace Assimp {
// ---------------------------------------------------------------------------
/// @brief This helper class supports some basic geometry algorithms.
// ---------------------------------------------------------------------------
class GeometryUtils {
class ASSIMP_API GeometryUtils {
public:
static ai_real heron( ai_real a, ai_real b, ai_real c );
@ -55,13 +55,27 @@ public:
/// @param vA Vector a.
/// @param vB Vector b.
/// @return The distance.
static ai_real distance3D( const aiVector3D &vA, aiVector3D &vB );
static ai_real distance3D( const aiVector3D &vA, const aiVector3D &vB );
/// @brief Will calculate the area of a triangle described by a aiFace.
/// @param face The face
/// @param mesh The mesh containing the face
/// @return The area.
static ai_real calculateAreaOfTriangle( const aiFace& face, aiMesh* mesh );
/// @brief Will calculate the intersection between a ray and a plane
/// @param ray The ray to test for
/// @param planePos A point on the plane
/// @param planeNormal The plane normal to describe its orientation
/// @param pos The position of the intersection.
/// @return true is an intersection was detected, false if not.
static bool PlaneIntersect(const aiRay& ray, const aiVector3D& planePos, const aiVector3D& planeNormal, aiVector3D& pos);
/// @brief Will normalize an array of vectors.
/// @param vectorArrayIn The incoming arra of vectors.
/// @param vectorArrayOut The normalized vectors.
/// @param numVectors The array size.
static void normalizeVectorArray(aiVector3D *vectorArrayIn, aiVector3D *vectorArrayOut, size_t numVectors);
};
} // namespace Assimp

View File

@ -43,15 +43,18 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/DefaultLogger.hpp>
#include <assimp/postprocess.h>
#include <assimp/scene.h>
#include <iostream>
namespace Assimp {
/// The default class constructor.
ArmaturePopulate::ArmaturePopulate() = default;
static bool IsBoneNode(const aiString &bone_name, std::vector<aiBone *> &bones) {
for (aiBone *bone : bones) {
if (bone->mName == bone_name) {
return true;
}
}
/// The class destructor.
ArmaturePopulate::~ArmaturePopulate() = default;
return false;
}
bool ArmaturePopulate::IsActive(unsigned int pFlags) const {
return (pFlags & aiProcess_PopulateArmatureData) != 0;
@ -70,7 +73,7 @@ void ArmaturePopulate::Execute(aiScene *out) {
BuildBoneList(out->mRootNode, out->mRootNode, out, bones);
BuildNodeList(out->mRootNode, nodes);
BuildBoneStack(out->mRootNode, out->mRootNode, out, bones, bone_stack, nodes);
BuildBoneStack(out->mRootNode, out, bones, bone_stack, nodes);
ASSIMP_LOG_DEBUG("Bone stack size: ", bone_stack.size());
@ -78,9 +81,8 @@ void ArmaturePopulate::Execute(aiScene *out) {
aiBone *bone = kvp.first;
aiNode *bone_node = kvp.second;
ASSIMP_LOG_VERBOSE_DEBUG("active node lookup: ", bone->mName.C_Str());
// lcl transform grab - done in generate_nodes :)
// bone->mOffsetMatrix = bone_node->mTransformation;
aiNode *armature = GetArmatureRoot(bone_node, bones);
ai_assert(armature);
@ -159,8 +161,7 @@ void ArmaturePopulate::BuildNodeList(const aiNode *current_node,
// A bone stack allows us to have multiple armatures, with the same bone names
// A bone stack allows us also to retrieve bones true transform even with
// duplicate names :)
void ArmaturePopulate::BuildBoneStack(aiNode *,
const aiNode *root_node,
void ArmaturePopulate::BuildBoneStack(const aiNode *root_node,
const aiScene*,
const std::vector<aiBone *> &bones,
std::map<aiBone *, aiNode *> &bone_stack,
@ -196,8 +197,7 @@ void ArmaturePopulate::BuildBoneStack(aiNode *,
// This is required to be detected for a bone initially, it will recurse up
// until it cannot find another bone and return the node No known failure
// points. (yet)
aiNode *ArmaturePopulate::GetArmatureRoot(aiNode *bone_node,
std::vector<aiBone *> &bone_list) {
aiNode *ArmaturePopulate::GetArmatureRoot(aiNode *bone_node, std::vector<aiBone *> &bone_list) {
while (nullptr != bone_node) {
if (!IsBoneNode(bone_node->mName, bone_list)) {
ASSIMP_LOG_VERBOSE_DEBUG("GetArmatureRoot() Found valid armature: ", bone_node->mName.C_Str());
@ -212,18 +212,6 @@ aiNode *ArmaturePopulate::GetArmatureRoot(aiNode *bone_node,
return nullptr;
}
// Simple IsBoneNode check if this could be a bone
bool ArmaturePopulate::IsBoneNode(const aiString &bone_name,
std::vector<aiBone *> &bones) {
for (aiBone *bone : bones) {
if (bone->mName == bone_name) {
return true;
}
}
return false;
}
// Pop this node by name from the stack if found
// Used in multiple armature situations with duplicate node / bone names
// Known flaw: cannot have nodes with bone names, will be fixed in later release

View File

@ -69,10 +69,10 @@ namespace Assimp {
class ASSIMP_API ArmaturePopulate : public BaseProcess {
public:
/// The default class constructor.
ArmaturePopulate();
ArmaturePopulate() = default;
/// The class destructor.
virtual ~ArmaturePopulate();
virtual ~ArmaturePopulate() = default;
/// Overwritten, @see BaseProcess
virtual bool IsActive( unsigned int pFlags ) const;
@ -86,9 +86,6 @@ public:
static aiNode *GetArmatureRoot(aiNode *bone_node,
std::vector<aiBone *> &bone_list);
static bool IsBoneNode(const aiString &bone_name,
std::vector<aiBone *> &bones);
static aiNode *GetNodeFromStack(const aiString &node_name,
std::vector<aiNode *> &nodes);
@ -99,7 +96,7 @@ public:
const aiScene *scene,
std::vector<aiBone *> &bones);
static void BuildBoneStack(aiNode *current_node, const aiNode *root_node,
static void BuildBoneStack(const aiNode *root_node,
const aiScene *scene,
const std::vector<aiBone *> &bones,
std::map<aiBone *, aiNode *> &bone_stack,
@ -108,5 +105,4 @@ public:
} // Namespace Assimp
#endif // SCALE_PROCESS_H_

View File

@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2022, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
@ -42,8 +41,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/** @file GenUVCoords step */
#include "ComputeUVMappingProcess.h"
#include "Geometry/GeometryUtils.h"
#include "ProcessHelper.h"
#include <assimp/Exceptional.h>
@ -51,39 +50,25 @@ using namespace Assimp;
namespace {
const static aiVector3D base_axis_y(0.0,1.0,0.0);
const static aiVector3D base_axis_x(1.0,0.0,0.0);
const static aiVector3D base_axis_z(0.0,0.0,1.0);
const static ai_real angle_epsilon = ai_real( 0.95 );
}
const static aiVector3D base_axis_y(0.0, 1.0, 0.0);
const static aiVector3D base_axis_x(1.0, 0.0, 0.0);
const static aiVector3D base_axis_z(0.0, 0.0, 1.0);
const static ai_real angle_epsilon = ai_real(0.95);
} // namespace
// ------------------------------------------------------------------------------------------------
// Returns whether the processing step is present in the given flag field.
bool ComputeUVMappingProcess::IsActive( unsigned int pFlags) const
{
return (pFlags & aiProcess_GenUVCoords) != 0;
}
// ------------------------------------------------------------------------------------------------
// Check whether a ray intersects a plane and find the intersection point
inline bool PlaneIntersect(const aiRay& ray, const aiVector3D& planePos,
const aiVector3D& planeNormal, aiVector3D& pos)
{
const ai_real b = planeNormal * (planePos - ray.pos);
ai_real h = ray.dir * planeNormal;
if ((h < 10e-5 && h > -10e-5) || (h = b/h) < 0)
return false;
pos = ray.pos + (ray.dir * h);
return true;
bool ComputeUVMappingProcess::IsActive(unsigned int pFlags) const {
return (pFlags & aiProcess_GenUVCoords) != 0;
}
// ------------------------------------------------------------------------------------------------
// Find the first empty UV channel in a mesh
inline unsigned int FindEmptyUVChannel (aiMesh* mesh)
{
for (unsigned int m = 0; m < AI_MAX_NUMBER_OF_TEXTURECOORDS;++m)
if (!mesh->mTextureCoords[m])return m;
inline unsigned int FindEmptyUVChannel(aiMesh *mesh) {
for (unsigned int m = 0; m < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++m)
if (!mesh->mTextureCoords[m]) {
return m;
}
ASSIMP_LOG_ERROR("Unable to compute UV coordinates, no free UV slot found");
return UINT_MAX;
@ -91,22 +76,22 @@ inline unsigned int FindEmptyUVChannel (aiMesh* mesh)
// ------------------------------------------------------------------------------------------------
// Try to remove UV seams
void RemoveUVSeams (aiMesh* mesh, aiVector3D* out)
{
void RemoveUVSeams(aiMesh *mesh, aiVector3D *out) {
// TODO: just a very rough algorithm. I think it could be done
// much easier, but I don't know how and am currently too tired to
// to think about a better solution.
const static ai_real LOWER_LIMIT = ai_real( 0.1 );
const static ai_real UPPER_LIMIT = ai_real( 0.9 );
const static ai_real LOWER_LIMIT = ai_real(0.1);
const static ai_real UPPER_LIMIT = ai_real(0.9);
const static ai_real LOWER_EPSILON = ai_real( 10e-3 );
const static ai_real UPPER_EPSILON = ai_real( 1.0-10e-3 );
const static ai_real LOWER_EPSILON = ai_real(10e-3);
const static ai_real UPPER_EPSILON = ai_real(1.0 - 10e-3);
for (unsigned int fidx = 0; fidx < mesh->mNumFaces;++fidx)
{
const aiFace& face = mesh->mFaces[fidx];
if (face.mNumIndices < 3) continue; // triangles and polygons only, please
for (unsigned int fidx = 0; fidx < mesh->mNumFaces; ++fidx) {
const aiFace &face = mesh->mFaces[fidx];
if (face.mNumIndices < 3) {
continue; // triangles and polygons only, please
}
unsigned int smallV = face.mNumIndices, large = smallV;
bool zero = false, one = false, round_to_zero = false;
@ -115,20 +100,18 @@ void RemoveUVSeams (aiMesh* mesh, aiVector3D* out)
// but the assumption that a face with at least one very small
// on the one side and one very large U coord on the other side
// lies on a UV seam should work for most cases.
for (unsigned int n = 0; n < face.mNumIndices;++n)
{
if (out[face.mIndices[n]].x < LOWER_LIMIT)
{
for (unsigned int n = 0; n < face.mNumIndices; ++n) {
if (out[face.mIndices[n]].x < LOWER_LIMIT) {
smallV = n;
// If we have a U value very close to 0 we can't
// round the others to 0, too.
if (out[face.mIndices[n]].x <= LOWER_EPSILON)
zero = true;
else round_to_zero = true;
else
round_to_zero = true;
}
if (out[face.mIndices[n]].x > UPPER_LIMIT)
{
if (out[face.mIndices[n]].x > UPPER_LIMIT) {
large = n;
// If we have a U value very close to 1 we can't
@ -137,10 +120,8 @@ void RemoveUVSeams (aiMesh* mesh, aiVector3D* out)
one = true;
}
}
if (smallV != face.mNumIndices && large != face.mNumIndices)
{
for (unsigned int n = 0; n < face.mNumIndices;++n)
{
if (smallV != face.mNumIndices && large != face.mNumIndices) {
for (unsigned int n = 0; n < face.mNumIndices; ++n) {
// If the u value is over the upper limit and no other u
// value of that face is 0, round it to 0
if (out[face.mIndices[n]].x > UPPER_LIMIT && !zero)
@ -156,9 +137,8 @@ void RemoveUVSeams (aiMesh* mesh, aiVector3D* out)
// Due to numerical inaccuracies one U coord becomes 0, the
// other 1. But we do still have a third UV coord to determine
// to which side we must round to.
else if (one && zero)
{
if (round_to_zero && out[face.mIndices[n]].x >= UPPER_EPSILON)
else if (one && zero) {
if (round_to_zero && out[face.mIndices[n]].x >= UPPER_EPSILON)
out[face.mIndices[n]].x = 0.0;
else if (!round_to_zero && out[face.mIndices[n]].x <= LOWER_EPSILON)
out[face.mIndices[n]].x = 1.0;
@ -169,8 +149,7 @@ void RemoveUVSeams (aiMesh* mesh, aiVector3D* out)
}
// ------------------------------------------------------------------------------------------------
void ComputeUVMappingProcess::ComputeSphereMapping(aiMesh* mesh,const aiVector3D& axis, aiVector3D* out)
{
void ComputeUVMappingProcess::ComputeSphereMapping(aiMesh *mesh, const aiVector3D &axis, aiVector3D *out) {
aiVector3D center, min, max;
FindMeshCenter(mesh, center, min, max);
@ -178,7 +157,7 @@ void ComputeUVMappingProcess::ComputeSphereMapping(aiMesh* mesh,const aiVector3D
// currently the mapping axis will always be one of x,y,z, except if the
// PretransformVertices step is used (it transforms the meshes into worldspace,
// thus changing the mapping axis)
if (axis * base_axis_x >= angle_epsilon) {
if (axis * base_axis_x >= angle_epsilon) {
// For each point get a normalized projection vector in the sphere,
// get its longitude and latitude and map them to their respective
@ -192,58 +171,54 @@ void ComputeUVMappingProcess::ComputeSphereMapping(aiMesh* mesh,const aiVector3D
// Thus we can derive:
// lat = arcsin (z)
// lon = arctan (y/x)
for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt) {
const aiVector3D diff = (mesh->mVertices[pnt]-center).Normalize();
out[pnt] = aiVector3D((std::atan2(diff.z, diff.y) + AI_MATH_PI_F ) / AI_MATH_TWO_PI_F,
(std::asin (diff.x) + AI_MATH_HALF_PI_F) / AI_MATH_PI_F, 0.0);
for (unsigned int pnt = 0; pnt < mesh->mNumVertices; ++pnt) {
const aiVector3D diff = (mesh->mVertices[pnt] - center).Normalize();
out[pnt] = aiVector3D((std::atan2(diff.z, diff.y) + AI_MATH_PI_F) / AI_MATH_TWO_PI_F,
(std::asin(diff.x) + AI_MATH_HALF_PI_F) / AI_MATH_PI_F, 0.0);
}
}
else if (axis * base_axis_y >= angle_epsilon) {
} else if (axis * base_axis_y >= angle_epsilon) {
// ... just the same again
for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt) {
const aiVector3D diff = (mesh->mVertices[pnt]-center).Normalize();
out[pnt] = aiVector3D((std::atan2(diff.x, diff.z) + AI_MATH_PI_F ) / AI_MATH_TWO_PI_F,
(std::asin (diff.y) + AI_MATH_HALF_PI_F) / AI_MATH_PI_F, 0.0);
for (unsigned int pnt = 0; pnt < mesh->mNumVertices; ++pnt) {
const aiVector3D diff = (mesh->mVertices[pnt] - center).Normalize();
out[pnt] = aiVector3D((std::atan2(diff.x, diff.z) + AI_MATH_PI_F) / AI_MATH_TWO_PI_F,
(std::asin(diff.y) + AI_MATH_HALF_PI_F) / AI_MATH_PI_F, 0.0);
}
}
else if (axis * base_axis_z >= angle_epsilon) {
} else if (axis * base_axis_z >= angle_epsilon) {
// ... just the same again
for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt) {
const aiVector3D diff = (mesh->mVertices[pnt]-center).Normalize();
out[pnt] = aiVector3D((std::atan2(diff.y, diff.x) + AI_MATH_PI_F ) / AI_MATH_TWO_PI_F,
(std::asin (diff.z) + AI_MATH_HALF_PI_F) / AI_MATH_PI_F, 0.0);
for (unsigned int pnt = 0; pnt < mesh->mNumVertices; ++pnt) {
const aiVector3D diff = (mesh->mVertices[pnt] - center).Normalize();
out[pnt] = aiVector3D((std::atan2(diff.y, diff.x) + AI_MATH_PI_F) / AI_MATH_TWO_PI_F,
(std::asin(diff.z) + AI_MATH_HALF_PI_F) / AI_MATH_PI_F, 0.0);
}
}
// slower code path in case the mapping axis is not one of the coordinate system axes
else {
else {
aiMatrix4x4 mTrafo;
aiMatrix4x4::FromToMatrix(axis,base_axis_y,mTrafo);
aiMatrix4x4::FromToMatrix(axis, base_axis_y, mTrafo);
// again the same, except we're applying a transformation now
for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt) {
const aiVector3D diff = ((mTrafo*mesh->mVertices[pnt])-center).Normalize();
out[pnt] = aiVector3D((std::atan2(diff.y, diff.x) + AI_MATH_PI_F ) / AI_MATH_TWO_PI_F,
(std::asin(diff.z) + AI_MATH_HALF_PI_F) / AI_MATH_PI_F, 0.0);
for (unsigned int pnt = 0; pnt < mesh->mNumVertices; ++pnt) {
const aiVector3D diff = ((mTrafo * mesh->mVertices[pnt]) - center).Normalize();
out[pnt] = aiVector3D((std::atan2(diff.y, diff.x) + AI_MATH_PI_F) / AI_MATH_TWO_PI_F,
(std::asin(diff.z) + AI_MATH_HALF_PI_F) / AI_MATH_PI_F, 0.0);
}
}
// Now find and remove UV seams. A seam occurs if a face has a tcoord
// close to zero on the one side, and a tcoord close to one on the
// other side.
RemoveUVSeams(mesh,out);
RemoveUVSeams(mesh, out);
}
// ------------------------------------------------------------------------------------------------
void ComputeUVMappingProcess::ComputeCylinderMapping(aiMesh* mesh,const aiVector3D& axis, aiVector3D* out)
{
void ComputeUVMappingProcess::ComputeCylinderMapping(aiMesh *mesh, const aiVector3D &axis, aiVector3D *out) {
aiVector3D center, min, max;
// If the axis is one of x,y,z run a faster code path. It's worth the extra effort ...
// currently the mapping axis will always be one of x,y,z, except if the
// PretransformVertices step is used (it transforms the meshes into worldspace,
// thus changing the mapping axis)
if (axis * base_axis_x >= angle_epsilon) {
if (axis * base_axis_x >= angle_epsilon) {
FindMeshCenter(mesh, center, min, max);
const ai_real diff = max.x - min.x;
@ -251,116 +226,110 @@ void ComputeUVMappingProcess::ComputeCylinderMapping(aiMesh* mesh,const aiVector
// directly to the texture V axis. The other axis is derived from
// the angle between ( p.x - c.x, p.y - c.y ) and (1,0), where
// 'c' is the center point of the mesh.
for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt) {
const aiVector3D& pos = mesh->mVertices[pnt];
aiVector3D& uv = out[pnt];
for (unsigned int pnt = 0; pnt < mesh->mNumVertices; ++pnt) {
const aiVector3D &pos = mesh->mVertices[pnt];
aiVector3D &uv = out[pnt];
uv.y = (pos.x - min.x) / diff;
uv.x = (std::atan2( pos.z - center.z, pos.y - center.y) +(ai_real)AI_MATH_PI ) / (ai_real)AI_MATH_TWO_PI;
uv.x = (std::atan2(pos.z - center.z, pos.y - center.y) + (ai_real)AI_MATH_PI) / (ai_real)AI_MATH_TWO_PI;
}
}
else if (axis * base_axis_y >= angle_epsilon) {
} else if (axis * base_axis_y >= angle_epsilon) {
FindMeshCenter(mesh, center, min, max);
const ai_real diff = max.y - min.y;
// just the same ...
for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt) {
const aiVector3D& pos = mesh->mVertices[pnt];
aiVector3D& uv = out[pnt];
for (unsigned int pnt = 0; pnt < mesh->mNumVertices; ++pnt) {
const aiVector3D &pos = mesh->mVertices[pnt];
aiVector3D &uv = out[pnt];
uv.y = (pos.y - min.y) / diff;
uv.x = (std::atan2( pos.x - center.x, pos.z - center.z) +(ai_real)AI_MATH_PI ) / (ai_real)AI_MATH_TWO_PI;
uv.x = (std::atan2(pos.x - center.x, pos.z - center.z) + (ai_real)AI_MATH_PI) / (ai_real)AI_MATH_TWO_PI;
}
}
else if (axis * base_axis_z >= angle_epsilon) {
} else if (axis * base_axis_z >= angle_epsilon) {
FindMeshCenter(mesh, center, min, max);
const ai_real diff = max.z - min.z;
// just the same ...
for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt) {
const aiVector3D& pos = mesh->mVertices[pnt];
aiVector3D& uv = out[pnt];
for (unsigned int pnt = 0; pnt < mesh->mNumVertices; ++pnt) {
const aiVector3D &pos = mesh->mVertices[pnt];
aiVector3D &uv = out[pnt];
uv.y = (pos.z - min.z) / diff;
uv.x = (std::atan2( pos.y - center.y, pos.x - center.x) +(ai_real)AI_MATH_PI ) / (ai_real)AI_MATH_TWO_PI;
uv.x = (std::atan2(pos.y - center.y, pos.x - center.x) + (ai_real)AI_MATH_PI) / (ai_real)AI_MATH_TWO_PI;
}
}
// slower code path in case the mapping axis is not one of the coordinate system axes
else {
aiMatrix4x4 mTrafo;
aiMatrix4x4::FromToMatrix(axis,base_axis_y,mTrafo);
FindMeshCenterTransformed(mesh, center, min, max,mTrafo);
aiMatrix4x4::FromToMatrix(axis, base_axis_y, mTrafo);
FindMeshCenterTransformed(mesh, center, min, max, mTrafo);
const ai_real diff = max.y - min.y;
// again the same, except we're applying a transformation now
for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt){
const aiVector3D pos = mTrafo* mesh->mVertices[pnt];
aiVector3D& uv = out[pnt];
for (unsigned int pnt = 0; pnt < mesh->mNumVertices; ++pnt) {
const aiVector3D pos = mTrafo * mesh->mVertices[pnt];
aiVector3D &uv = out[pnt];
uv.y = (pos.y - min.y) / diff;
uv.x = (std::atan2( pos.x - center.x, pos.z - center.z) +(ai_real)AI_MATH_PI ) / (ai_real)AI_MATH_TWO_PI;
uv.x = (std::atan2(pos.x - center.x, pos.z - center.z) + (ai_real)AI_MATH_PI) / (ai_real)AI_MATH_TWO_PI;
}
}
// Now find and remove UV seams. A seam occurs if a face has a tcoord
// close to zero on the one side, and a tcoord close to one on the
// other side.
RemoveUVSeams(mesh,out);
RemoveUVSeams(mesh, out);
}
// ------------------------------------------------------------------------------------------------
void ComputeUVMappingProcess::ComputePlaneMapping(aiMesh* mesh,const aiVector3D& axis, aiVector3D* out)
{
ai_real diffu,diffv;
void ComputeUVMappingProcess::ComputePlaneMapping(aiMesh *mesh, const aiVector3D &axis, aiVector3D *out) {
ai_real diffu, diffv;
aiVector3D center, min, max;
// If the axis is one of x,y,z run a faster code path. It's worth the extra effort ...
// currently the mapping axis will always be one of x,y,z, except if the
// PretransformVertices step is used (it transforms the meshes into worldspace,
// thus changing the mapping axis)
if (axis * base_axis_x >= angle_epsilon) {
if (axis * base_axis_x >= angle_epsilon) {
FindMeshCenter(mesh, center, min, max);
diffu = max.z - min.z;
diffv = max.y - min.y;
for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt) {
const aiVector3D& pos = mesh->mVertices[pnt];
out[pnt].Set((pos.z - min.z) / diffu,(pos.y - min.y) / diffv,0.0);
for (unsigned int pnt = 0; pnt < mesh->mNumVertices; ++pnt) {
const aiVector3D &pos = mesh->mVertices[pnt];
out[pnt].Set((pos.z - min.z) / diffu, (pos.y - min.y) / diffv, 0.0);
}
}
else if (axis * base_axis_y >= angle_epsilon) {
} else if (axis * base_axis_y >= angle_epsilon) {
FindMeshCenter(mesh, center, min, max);
diffu = max.x - min.x;
diffv = max.z - min.z;
for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt) {
const aiVector3D& pos = mesh->mVertices[pnt];
out[pnt].Set((pos.x - min.x) / diffu,(pos.z - min.z) / diffv,0.0);
for (unsigned int pnt = 0; pnt < mesh->mNumVertices; ++pnt) {
const aiVector3D &pos = mesh->mVertices[pnt];
out[pnt].Set((pos.x - min.x) / diffu, (pos.z - min.z) / diffv, 0.0);
}
}
else if (axis * base_axis_z >= angle_epsilon) {
} else if (axis * base_axis_z >= angle_epsilon) {
FindMeshCenter(mesh, center, min, max);
diffu = max.x - min.x;
diffv = max.y - min.y;
for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt) {
const aiVector3D& pos = mesh->mVertices[pnt];
out[pnt].Set((pos.x - min.x) / diffu,(pos.y - min.y) / diffv,0.0);
for (unsigned int pnt = 0; pnt < mesh->mNumVertices; ++pnt) {
const aiVector3D &pos = mesh->mVertices[pnt];
out[pnt].Set((pos.x - min.x) / diffu, (pos.y - min.y) / diffv, 0.0);
}
}
// slower code path in case the mapping axis is not one of the coordinate system axes
else
{
else {
aiMatrix4x4 mTrafo;
aiMatrix4x4::FromToMatrix(axis,base_axis_y,mTrafo);
FindMeshCenterTransformed(mesh, center, min, max,mTrafo);
aiMatrix4x4::FromToMatrix(axis, base_axis_y, mTrafo);
FindMeshCenterTransformed(mesh, center, min, max, mTrafo);
diffu = max.x - min.x;
diffv = max.z - min.z;
// again the same, except we're applying a transformation now
for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt) {
for (unsigned int pnt = 0; pnt < mesh->mNumVertices; ++pnt) {
const aiVector3D pos = mTrafo * mesh->mVertices[pnt];
out[pnt].Set((pos.x - min.x) / diffu,(pos.z - min.z) / diffv,0.0);
out[pnt].Set((pos.x - min.x) / diffu, (pos.z - min.z) / diffv, 0.0);
}
}
@ -368,14 +337,12 @@ void ComputeUVMappingProcess::ComputePlaneMapping(aiMesh* mesh,const aiVector3D&
}
// ------------------------------------------------------------------------------------------------
void ComputeUVMappingProcess::ComputeBoxMapping( aiMesh*, aiVector3D* )
{
void ComputeUVMappingProcess::ComputeBoxMapping(aiMesh *, aiVector3D *) {
ASSIMP_LOG_ERROR("Mapping type currently not implemented");
}
// ------------------------------------------------------------------------------------------------
void ComputeUVMappingProcess::Execute( aiScene* pScene)
{
void ComputeUVMappingProcess::Execute(aiScene *pScene) {
ASSIMP_LOG_DEBUG("GenUVCoordsProcess begin");
char buffer[1024];
@ -386,23 +353,18 @@ void ComputeUVMappingProcess::Execute( aiScene* pScene)
/* Iterate through all materials and search for non-UV mapped textures
*/
for (unsigned int i = 0; i < pScene->mNumMaterials;++i)
{
for (unsigned int i = 0; i < pScene->mNumMaterials; ++i) {
mappingStack.clear();
aiMaterial* mat = pScene->mMaterials[i];
for (unsigned int a = 0; a < mat->mNumProperties;++a)
{
aiMaterialProperty* prop = mat->mProperties[a];
if (!::strcmp( prop->mKey.data, "$tex.mapping"))
{
aiTextureMapping& mapping = *((aiTextureMapping*)prop->mData);
if (aiTextureMapping_UV != mapping)
{
if (!DefaultLogger::isNullLogger())
{
aiMaterial *mat = pScene->mMaterials[i];
for (unsigned int a = 0; a < mat->mNumProperties; ++a) {
aiMaterialProperty *prop = mat->mProperties[a];
if (!::strcmp(prop->mKey.data, "$tex.mapping")) {
aiTextureMapping &mapping = *((aiTextureMapping *)prop->mData);
if (aiTextureMapping_UV != mapping) {
if (!DefaultLogger::isNullLogger()) {
ai_snprintf(buffer, 1024, "Found non-UV mapped texture (%s,%u). Mapping type: %s",
aiTextureTypeToString((aiTextureType)prop->mSemantic),prop->mIndex,
MappingTypeToString(mapping));
aiTextureTypeToString((aiTextureType)prop->mSemantic), prop->mIndex,
MappingTypeToString(mapping));
ASSIMP_LOG_INFO(buffer);
}
@ -410,70 +372,62 @@ void ComputeUVMappingProcess::Execute( aiScene* pScene)
if (aiTextureMapping_OTHER == mapping)
continue;
MappingInfo info (mapping);
MappingInfo info(mapping);
// Get further properties - currently only the major axis
for (unsigned int a2 = 0; a2 < mat->mNumProperties;++a2)
{
aiMaterialProperty* prop2 = mat->mProperties[a2];
for (unsigned int a2 = 0; a2 < mat->mNumProperties; ++a2) {
aiMaterialProperty *prop2 = mat->mProperties[a2];
if (prop2->mSemantic != prop->mSemantic || prop2->mIndex != prop->mIndex)
continue;
if ( !::strcmp( prop2->mKey.data, "$tex.mapaxis")) {
info.axis = *((aiVector3D*)prop2->mData);
if (!::strcmp(prop2->mKey.data, "$tex.mapaxis")) {
info.axis = *((aiVector3D *)prop2->mData);
break;
}
}
unsigned int idx( 99999999 );
unsigned int idx(99999999);
// Check whether we have this mapping mode already
std::list<MappingInfo>::iterator it = std::find (mappingStack.begin(),mappingStack.end(), info);
if (mappingStack.end() != it)
{
std::list<MappingInfo>::iterator it = std::find(mappingStack.begin(), mappingStack.end(), info);
if (mappingStack.end() != it) {
idx = (*it).uv;
}
else
{
} else {
/* We have found a non-UV mapped texture. Now
* we need to find all meshes using this material
* that we can compute UV channels for them.
*/
for (unsigned int m = 0; m < pScene->mNumMeshes;++m)
{
aiMesh* mesh = pScene->mMeshes[m];
* we need to find all meshes using this material
* that we can compute UV channels for them.
*/
for (unsigned int m = 0; m < pScene->mNumMeshes; ++m) {
aiMesh *mesh = pScene->mMeshes[m];
unsigned int outIdx = 0;
if ( mesh->mMaterialIndex != i || ( outIdx = FindEmptyUVChannel(mesh) ) == UINT_MAX ||
!mesh->mNumVertices)
{
if (mesh->mMaterialIndex != i || (outIdx = FindEmptyUVChannel(mesh)) == UINT_MAX ||
!mesh->mNumVertices) {
continue;
}
// Allocate output storage
aiVector3D* p = mesh->mTextureCoords[outIdx] = new aiVector3D[mesh->mNumVertices];
aiVector3D *p = mesh->mTextureCoords[outIdx] = new aiVector3D[mesh->mNumVertices];
switch (mapping)
{
switch (mapping) {
case aiTextureMapping_SPHERE:
ComputeSphereMapping(mesh,info.axis,p);
ComputeSphereMapping(mesh, info.axis, p);
break;
case aiTextureMapping_CYLINDER:
ComputeCylinderMapping(mesh,info.axis,p);
ComputeCylinderMapping(mesh, info.axis, p);
break;
case aiTextureMapping_PLANE:
ComputePlaneMapping(mesh,info.axis,p);
ComputePlaneMapping(mesh, info.axis, p);
break;
case aiTextureMapping_BOX:
ComputeBoxMapping(mesh,p);
ComputeBoxMapping(mesh, p);
break;
default:
ai_assert(false);
}
if (m && idx != outIdx)
{
if (m && idx != outIdx) {
ASSIMP_LOG_WARN("UV index mismatch. Not all meshes assigned to "
"this material have equal numbers of UV channels. The UV index stored in "
"the material structure does therefore not apply for all meshes. ");
"this material have equal numbers of UV channels. The UV index stored in "
"the material structure does therefore not apply for all meshes. ");
}
idx = outIdx;
}
@ -483,7 +437,7 @@ void ComputeUVMappingProcess::Execute( aiScene* pScene)
// Update the material property list
mapping = aiTextureMapping_UV;
((aiMaterial*)mat)->AddProperty(&idx,1,AI_MATKEY_UVWSRC(prop->mSemantic,prop->mIndex));
((aiMaterial *)mat)->AddProperty(&idx, 1, AI_MATKEY_UVWSRC(prop->mSemantic, prop->mIndex));
}
}
}

View File

@ -5,8 +5,6 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2022, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
@ -113,6 +111,12 @@ void MakeLeftHandedProcess::Execute(aiScene *pScene) {
ProcessAnimation(nodeAnim);
}
}
// process the cameras accordingly
for( unsigned int a = 0; a < pScene->mNumCameras; ++a)
{
ProcessCamera(pScene->mCameras[a]);
}
ASSIMP_LOG_DEBUG("MakeLeftHandedProcess finished");
}
@ -219,18 +223,18 @@ void MakeLeftHandedProcess::ProcessAnimation(aiNodeAnim *pAnim) {
// rotation keys
for (unsigned int a = 0; a < pAnim->mNumRotationKeys; a++) {
/* That's the safe version, but the float errors add up. So we try the short version instead
aiMatrix3x3 rotmat = pAnim->mRotationKeys[a].mValue.GetMatrix();
rotmat.a3 = -rotmat.a3; rotmat.b3 = -rotmat.b3;
rotmat.c1 = -rotmat.c1; rotmat.c2 = -rotmat.c2;
aiQuaternion rotquat( rotmat);
pAnim->mRotationKeys[a].mValue = rotquat;
*/
pAnim->mRotationKeys[a].mValue.x *= -1.0f;
pAnim->mRotationKeys[a].mValue.y *= -1.0f;
}
}
// ------------------------------------------------------------------------------------------------
// Converts a single camera to left handed coordinates.
void MakeLeftHandedProcess::ProcessCamera( aiCamera* pCam)
{
pCam->mLookAt = ai_real(2.0f) * pCam->mPosition - pCam->mLookAt;
}
#endif // !! ASSIMP_BUILD_NO_MAKELEFTHANDED_PROCESS
#ifndef ASSIMP_BUILD_NO_FLIPUVS_PROCESS
// # FlipUVsProcess

View File

@ -58,6 +58,7 @@ struct aiMesh;
struct aiNodeAnim;
struct aiNode;
struct aiMaterial;
struct aiCamera;
namespace Assimp {
@ -109,6 +110,14 @@ protected:
* @param pAnim The bone animation to transform
*/
void ProcessAnimation( aiNodeAnim* pAnim);
// -------------------------------------------------------------------
/** Converts a single camera to left handed coordinates.
* The camera viewing direction is inverted by reflecting mLookAt
* across mPosition.
* @param pCam The camera to convert
*/
void ProcessCamera( aiCamera* pCam);
};

View File

@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2022, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
@ -87,7 +86,7 @@ void DeboneProcess::Execute( aiScene* pScene) {
if(!!mNumBonesCanDoWithout && (!mAllOrNone||mNumBonesCanDoWithout==mNumBones)) {
for(unsigned int a = 0; a < pScene->mNumMeshes; a++) {
if(splitList[a]) {
numSplits++;
++numSplits;
}
}
}
@ -119,8 +118,8 @@ void DeboneProcess::Execute( aiScene* pScene) {
aiNode *theNode = find ? pScene->mRootNode->FindNode(*find) : nullptr;
std::pair<unsigned int,aiNode*> push_pair(static_cast<unsigned int>(meshes.size()),theNode);
mSubMeshIndices[a].push_back(push_pair);
meshes.push_back(newMeshes[b].first);
mSubMeshIndices[a].emplace_back(push_pair);
meshes.emplace_back(newMeshes[b].first);
out+=newMeshes[b].first->mNumBones;
}
@ -360,9 +359,7 @@ void DeboneProcess::UpdateNode(aiNode* pNode) const {
unsigned int m = static_cast<unsigned int>(pNode->mNumMeshes), n = static_cast<unsigned int>(mSubMeshIndices.size());
// first pass, look for meshes which have not moved
for(unsigned int a=0;a<m;a++) {
unsigned int srcIndex = pNode->mMeshes[a];
const std::vector< std::pair< unsigned int,aiNode* > > &subMeshes = mSubMeshIndices[srcIndex];
unsigned int nSubmeshes = static_cast<unsigned int>(subMeshes.size());
@ -376,8 +373,7 @@ void DeboneProcess::UpdateNode(aiNode* pNode) const {
// second pass, collect deboned meshes
for(unsigned int a=0;a<n;a++)
{
for(unsigned int a=0;a<n;a++) {
const std::vector< std::pair< unsigned int,aiNode* > > &subMeshes = mSubMeshIndices[a];
unsigned int nSubmeshes = static_cast<unsigned int>(subMeshes.size());

View File

@ -42,27 +42,26 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/** @file Implementation of the post processing step to drop face
* normals for all imported faces.
*/
* normals for all imported faces.
*/
#include "DropFaceNormalsProcess.h"
#include <assimp/Exceptional.h>
#include <assimp/postprocess.h>
#include <assimp/scene.h>
#include <assimp/DefaultLogger.hpp>
#include <assimp/Exceptional.h>
using namespace Assimp;
// ------------------------------------------------------------------------------------------------
// Returns whether the processing step is present in the given flag field.
bool DropFaceNormalsProcess::IsActive( unsigned int pFlags) const {
return (pFlags & aiProcess_DropNormals) != 0;
bool DropFaceNormalsProcess::IsActive(unsigned int pFlags) const {
return (pFlags & aiProcess_DropNormals) != 0;
}
// ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported data.
void DropFaceNormalsProcess::Execute( aiScene* pScene) {
void DropFaceNormalsProcess::Execute(aiScene *pScene) {
ASSIMP_LOG_DEBUG("DropFaceNormalsProcess begin");
if (pScene->mFlags & AI_SCENE_FLAGS_NON_VERBOSE_FORMAT) {
@ -70,21 +69,21 @@ void DropFaceNormalsProcess::Execute( aiScene* pScene) {
}
bool bHas = false;
for( unsigned int a = 0; a < pScene->mNumMeshes; a++) {
bHas |= this->DropMeshFaceNormals( pScene->mMeshes[a]);
for (unsigned int a = 0; a < pScene->mNumMeshes; a++) {
bHas |= this->DropMeshFaceNormals(pScene->mMeshes[a]);
}
if (bHas) {
if (bHas) {
ASSIMP_LOG_INFO("DropFaceNormalsProcess finished. "
"Face normals have been removed");
"Face normals have been removed");
} else {
ASSIMP_LOG_DEBUG("DropFaceNormalsProcess finished. "
"No normals were present");
"No normals were present");
}
}
// ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported data.
bool DropFaceNormalsProcess::DropMeshFaceNormals (aiMesh* mesh) {
bool DropFaceNormalsProcess::DropMeshFaceNormals(aiMesh *mesh) {
ai_assert(nullptr != mesh);
if (nullptr == mesh->mNormals) {

View File

@ -41,11 +41,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/** @file FindDegenerates.cpp
* @brief Implementation of the FindDegenerates post-process step.
*/
*/
#include "ProcessHelper.h"
#include "FindDegenerates.h"
#include "Geometry/GeometryUtils.h"
#include "ProcessHelper.h"
#include <assimp/Exceptional.h>
@ -54,35 +54,35 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
using namespace Assimp;
// Correct node indices to meshes and remove references to deleted mesh
static void updateSceneGraph(aiNode* pNode, const std::unordered_map<unsigned int, unsigned int>& meshMap);
static void updateSceneGraph(aiNode *pNode, const std::unordered_map<unsigned int, unsigned int> &meshMap);
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
FindDegeneratesProcess::FindDegeneratesProcess() :
mConfigRemoveDegenerates( false ),
mConfigCheckAreaOfTriangle( false ){
mConfigRemoveDegenerates(false),
mConfigCheckAreaOfTriangle(false) {
// empty
}
// ------------------------------------------------------------------------------------------------
// Returns whether the processing step is present in the given flag field.
bool FindDegeneratesProcess::IsActive( unsigned int pFlags) const {
bool FindDegeneratesProcess::IsActive(unsigned int pFlags) const {
return 0 != (pFlags & aiProcess_FindDegenerates);
}
// ------------------------------------------------------------------------------------------------
// Setup import configuration
void FindDegeneratesProcess::SetupProperties(const Importer* pImp) {
void FindDegeneratesProcess::SetupProperties(const Importer *pImp) {
// Get the current value of AI_CONFIG_PP_FD_REMOVE
mConfigRemoveDegenerates = (0 != pImp->GetPropertyInteger(AI_CONFIG_PP_FD_REMOVE,0));
mConfigCheckAreaOfTriangle = ( 0 != pImp->GetPropertyInteger(AI_CONFIG_PP_FD_CHECKAREA) );
mConfigRemoveDegenerates = (0 != pImp->GetPropertyInteger(AI_CONFIG_PP_FD_REMOVE, 0));
mConfigCheckAreaOfTriangle = (0 != pImp->GetPropertyInteger(AI_CONFIG_PP_FD_CHECKAREA));
}
// ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported data.
void FindDegeneratesProcess::Execute( aiScene* pScene) {
void FindDegeneratesProcess::Execute(aiScene *pScene) {
ASSIMP_LOG_DEBUG("FindDegeneratesProcess begin");
if ( nullptr == pScene) {
if (nullptr == pScene) {
return;
}
@ -112,7 +112,7 @@ void FindDegeneratesProcess::Execute( aiScene* pScene) {
ASSIMP_LOG_DEBUG("FindDegeneratesProcess finished");
}
static void updateSceneGraph(aiNode* pNode, const std::unordered_map<unsigned int, unsigned int>& meshMap) {
static void updateSceneGraph(aiNode *pNode, const std::unordered_map<unsigned int, unsigned int> &meshMap) {
unsigned int targetIndex = 0;
for (unsigned i = 0; i < pNode->mNumMeshes; ++i) {
const unsigned int sourceMeshIndex = pNode->mMeshes[i];
@ -123,7 +123,7 @@ static void updateSceneGraph(aiNode* pNode, const std::unordered_map<unsigned in
}
}
pNode->mNumMeshes = targetIndex;
//recurse to all children
// recurse to all children
for (unsigned i = 0; i < pNode->mNumChildren; ++i) {
updateSceneGraph(pNode->mChildren[i], meshMap);
}
@ -131,17 +131,17 @@ static void updateSceneGraph(aiNode* pNode, const std::unordered_map<unsigned in
// ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported mesh
bool FindDegeneratesProcess::ExecuteOnMesh( aiMesh* mesh) {
bool FindDegeneratesProcess::ExecuteOnMesh(aiMesh *mesh) {
mesh->mPrimitiveTypes = 0;
std::vector<bool> remove_me;
if (mConfigRemoveDegenerates) {
remove_me.resize( mesh->mNumFaces, false );
remove_me.resize(mesh->mNumFaces, false);
}
unsigned int deg = 0, limit;
for ( unsigned int a = 0; a < mesh->mNumFaces; ++a ) {
aiFace& face = mesh->mFaces[a];
for (unsigned int a = 0; a < mesh->mNumFaces; ++a) {
aiFace &face = mesh->mFaces[a];
bool first = true;
// check whether the face contains degenerated entries
@ -151,43 +151,43 @@ bool FindDegeneratesProcess::ExecuteOnMesh( aiMesh* mesh) {
// double points may not come directly after another.
limit = face.mNumIndices;
if (face.mNumIndices > 4) {
limit = std::min( limit, i+2 );
limit = std::min(limit, i + 2);
}
for (unsigned int t = i+1; t < limit; ++t) {
if (mesh->mVertices[face.mIndices[ i ] ] == mesh->mVertices[ face.mIndices[ t ] ]) {
for (unsigned int t = i + 1; t < limit; ++t) {
if (mesh->mVertices[face.mIndices[i]] == mesh->mVertices[face.mIndices[t]]) {
// we have found a matching vertex position
// remove the corresponding index from the array
--face.mNumIndices;
--limit;
for (unsigned int m = t; m < face.mNumIndices; ++m) {
face.mIndices[ m ] = face.mIndices[ m+1 ];
face.mIndices[m] = face.mIndices[m + 1];
}
--t;
// NOTE: we set the removed vertex index to an unique value
// to make sure the developer gets notified when his
// application attempts to access this data.
face.mIndices[ face.mNumIndices ] = 0xdeadbeef;
face.mIndices[face.mNumIndices] = 0xdeadbeef;
if(first) {
if (first) {
++deg;
first = false;
}
if ( mConfigRemoveDegenerates ) {
remove_me[ a ] = true;
if (mConfigRemoveDegenerates) {
remove_me[a] = true;
goto evil_jump_outside; // hrhrhrh ... yeah, this rocks baby!
}
}
}
if ( mConfigCheckAreaOfTriangle ) {
if ( face.mNumIndices == 3 ) {
ai_real area = GeometryUtils::calculateAreaOfTriangle( face, mesh );
if (mConfigCheckAreaOfTriangle) {
if (face.mNumIndices == 3) {
ai_real area = GeometryUtils::calculateAreaOfTriangle(face, mesh);
if (area < ai_epsilon) {
if ( mConfigRemoveDegenerates ) {
remove_me[ a ] = true;
if (mConfigRemoveDegenerates) {
remove_me[a] = true;
++deg;
goto evil_jump_outside;
}
@ -199,8 +199,7 @@ bool FindDegeneratesProcess::ExecuteOnMesh( aiMesh* mesh) {
}
// We need to update the primitive flags array of the mesh.
switch (face.mNumIndices)
{
switch (face.mNumIndices) {
case 1u:
mesh->mPrimitiveTypes |= aiPrimitiveType_POINT;
break;
@ -214,30 +213,28 @@ bool FindDegeneratesProcess::ExecuteOnMesh( aiMesh* mesh) {
mesh->mPrimitiveTypes |= aiPrimitiveType_POLYGON;
break;
};
evil_jump_outside:
evil_jump_outside:
continue;
}
// If AI_CONFIG_PP_FD_REMOVE is true, remove degenerated faces from the import
if (mConfigRemoveDegenerates && deg) {
unsigned int n = 0;
for (unsigned int a = 0; a < mesh->mNumFaces; ++a)
{
aiFace& face_src = mesh->mFaces[a];
for (unsigned int a = 0; a < mesh->mNumFaces; ++a) {
aiFace &face_src = mesh->mFaces[a];
if (!remove_me[a]) {
aiFace& face_dest = mesh->mFaces[n++];
aiFace &face_dest = mesh->mFaces[n++];
// Do a manual copy, keep the index array
face_dest.mNumIndices = face_src.mNumIndices;
face_dest.mIndices = face_src.mIndices;
face_dest.mIndices = face_src.mIndices;
if (&face_src != &face_dest) {
// clear source
face_src.mNumIndices = 0;
face_src.mIndices = nullptr;
}
}
else {
} else {
// Otherwise delete it if we don't need this face
delete[] face_src.mIndices;
face_src.mIndices = nullptr;
@ -247,15 +244,15 @@ evil_jump_outside:
// Just leave the rest of the array unreferenced, we don't care for now
mesh->mNumFaces = n;
if (!mesh->mNumFaces) {
//The whole mesh consists of degenerated faces
//signal upward, that this mesh should be deleted.
// The whole mesh consists of degenerated faces
// signal upward, that this mesh should be deleted.
ASSIMP_LOG_VERBOSE_DEBUG("FindDegeneratesProcess removed a mesh full of degenerated primitives");
return true;
}
}
if (deg && !DefaultLogger::isNullLogger()) {
ASSIMP_LOG_WARN( "Found ", deg, " degenerated primitives");
ASSIMP_LOG_WARN("Found ", deg, " degenerated primitives");
}
return false;
}

View File

@ -5,8 +5,6 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2022, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
@ -41,9 +39,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
/** @file PretransformVertices.cpp
* @brief Implementation of the "PretransformVertices" post processing step
*/
/// @file PretransformVertices.cpp
/// @brief Implementation of the "PretransformVertices" post processing step
#include "PretransformVertices.h"
#include "ConvertToLHProcess.h"
@ -57,16 +54,44 @@ using namespace Assimp;
#define AI_PTVS_VERTEX 0x0
#define AI_PTVS_FACE 0x1
namespace {
// Get a bitwise combination identifying the vertex format of a mesh
static unsigned int GetMeshVFormat(aiMesh *pcMesh) {
// the vertex format is stored in aiMesh::mBones for later retrieval.
// there isn't a good reason to compute it a few hundred times
// from scratch. The pointer is unused as animations are lost
// during PretransformVertices.
if (pcMesh->mBones)
return (unsigned int)(uint64_t)pcMesh->mBones;
const unsigned int iRet = GetMeshVFormatUnique(pcMesh);
// store the value for later use
pcMesh->mBones = (aiBone **)(uint64_t)iRet;
return iRet;
}
// Get a list of all vertex formats that occur for a given material index
// The output list contains duplicate elements
static void GetVFormatList(const aiScene *pcScene, unsigned int iMat, std::list<unsigned int> &aiOut) {
for (unsigned int i = 0; i < pcScene->mNumMeshes; ++i) {
aiMesh *pcMesh = pcScene->mMeshes[i];
if (iMat == pcMesh->mMaterialIndex) {
aiOut.push_back(GetMeshVFormat(pcMesh));
}
}
}
}
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
PretransformVertices::PretransformVertices() :
configKeepHierarchy(false),
configNormalize(false),
configTransform(false),
configTransformation(),
mConfigPointCloud(false) {
// empty
}
mConfigKeepHierarchy(false),
mConfigNormalize(false),
mConfigTransform(false),
mConfigTransformation(),
mConfigPointCloud(false) {}
// ------------------------------------------------------------------------------------------------
// Returns whether the processing step is present in the given flag field.
@ -79,11 +104,11 @@ bool PretransformVertices::IsActive(unsigned int pFlags) const {
void PretransformVertices::SetupProperties(const Importer *pImp) {
// Get the current value of AI_CONFIG_PP_PTV_KEEP_HIERARCHY, AI_CONFIG_PP_PTV_NORMALIZE,
// AI_CONFIG_PP_PTV_ADD_ROOT_TRANSFORMATION and AI_CONFIG_PP_PTV_ROOT_TRANSFORMATION
configKeepHierarchy = (0 != pImp->GetPropertyInteger(AI_CONFIG_PP_PTV_KEEP_HIERARCHY, 0));
configNormalize = (0 != pImp->GetPropertyInteger(AI_CONFIG_PP_PTV_NORMALIZE, 0));
configTransform = (0 != pImp->GetPropertyInteger(AI_CONFIG_PP_PTV_ADD_ROOT_TRANSFORMATION, 0));
mConfigKeepHierarchy = (0 != pImp->GetPropertyInteger(AI_CONFIG_PP_PTV_KEEP_HIERARCHY, 0));
mConfigNormalize = (0 != pImp->GetPropertyInteger(AI_CONFIG_PP_PTV_NORMALIZE, 0));
mConfigTransform = (0 != pImp->GetPropertyInteger(AI_CONFIG_PP_PTV_ADD_ROOT_TRANSFORMATION, 0));
configTransformation = pImp->GetPropertyMatrix(AI_CONFIG_PP_PTV_ROOT_TRANSFORMATION, aiMatrix4x4());
mConfigTransformation = pImp->GetPropertyMatrix(AI_CONFIG_PP_PTV_ROOT_TRANSFORMATION, aiMatrix4x4());
mConfigPointCloud = pImp->GetPropertyBool(AI_CONFIG_EXPORT_POINT_CLOUDS);
}
@ -99,25 +124,7 @@ unsigned int PretransformVertices::CountNodes(const aiNode *pcNode) const {
}
// ------------------------------------------------------------------------------------------------
// Get a bitwise combination identifying the vertex format of a mesh
unsigned int PretransformVertices::GetMeshVFormat(aiMesh *pcMesh) const {
// the vertex format is stored in aiMesh::mBones for later retrieval.
// there isn't a good reason to compute it a few hundred times
// from scratch. The pointer is unused as animations are lost
// during PretransformVertices.
if (pcMesh->mBones)
return (unsigned int)(uint64_t)pcMesh->mBones;
const unsigned int iRet = GetMeshVFormatUnique(pcMesh);
// store the value for later use
pcMesh->mBones = (aiBone **)(uint64_t)iRet;
return iRet;
}
// ------------------------------------------------------------------------------------------------
// Count the number of vertices in the whole scene and a given
// material index
// Count the number of vertices in the whole scene and a given material index
void PretransformVertices::CountVerticesAndFaces(const aiScene *pcScene, const aiNode *pcNode, unsigned int iMat,
unsigned int iVFormat, unsigned int *piFaces, unsigned int *piVertices) const {
for (unsigned int i = 0; i < pcNode->mNumMeshes; ++i) {
@ -128,8 +135,7 @@ void PretransformVertices::CountVerticesAndFaces(const aiScene *pcScene, const a
}
}
for (unsigned int i = 0; i < pcNode->mNumChildren; ++i) {
CountVerticesAndFaces(pcScene, pcNode->mChildren[i], iMat,
iVFormat, piFaces, piVertices);
CountVerticesAndFaces(pcScene, pcNode->mChildren[i], iMat, iVFormat, piFaces, piVertices);
}
}
@ -272,19 +278,6 @@ void PretransformVertices::CollectData(const aiScene *pcScene, const aiNode *pcN
}
}
// ------------------------------------------------------------------------------------------------
// Get a list of all vertex formats that occur for a given material index
// The output list contains duplicate elements
void PretransformVertices::GetVFormatList(const aiScene *pcScene, unsigned int iMat,
std::list<unsigned int> &aiOut) const {
for (unsigned int i = 0; i < pcScene->mNumMeshes; ++i) {
aiMesh *pcMesh = pcScene->mMeshes[i];
if (iMat == pcMesh->mMaterialIndex) {
aiOut.push_back(GetMeshVFormat(pcMesh));
}
}
}
// ------------------------------------------------------------------------------------------------
// Compute the absolute transformation matrices of each node
void PretransformVertices::ComputeAbsoluteTransform(aiNode *pcNode) {
@ -297,39 +290,44 @@ void PretransformVertices::ComputeAbsoluteTransform(aiNode *pcNode) {
}
}
static void normalizeVectorArray(aiVector3D *vectorArrayIn, aiVector3D *vectorArrayOut, size_t numVectors) {
for (size_t i=0; i<numVectors; ++i) {
vectorArrayOut[i] = vectorArrayIn[i].Normalize();
}
}
// ------------------------------------------------------------------------------------------------
// Apply the node transformation to a mesh
void PretransformVertices::ApplyTransform(aiMesh *mesh, const aiMatrix4x4 &mat) const {
// Check whether we need to transform the coordinates at all
if (!mat.IsIdentity()) {
if (mat.IsIdentity()) {
return;
}
// Check for odd negative scale (mirror)
if (mesh->HasFaces() && mat.Determinant() < 0) {
// Reverse the mesh face winding order
FlipWindingOrderProcess::ProcessMesh(mesh);
// Check for odd negative scale (mirror)
if (mesh->HasFaces() && mat.Determinant() < 0) {
// Reverse the mesh face winding order
FlipWindingOrderProcess::ProcessMesh(mesh);
}
// Update positions
if (mesh->HasPositions()) {
for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
mesh->mVertices[i] = mat * mesh->mVertices[i];
}
}
// Update positions
if (mesh->HasPositions()) {
// Update normals and tangents
if (mesh->HasNormals() || mesh->HasTangentsAndBitangents()) {
const aiMatrix3x3 m = aiMatrix3x3(mat).Inverse().Transpose();
if (mesh->HasNormals()) {
normalizeVectorArray(mesh->mNormals, mesh->mNormals, mesh->mNumVertices);
}
if (mesh->HasTangentsAndBitangents()) {
for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
mesh->mVertices[i] = mat * mesh->mVertices[i];
}
}
// Update normals and tangents
if (mesh->HasNormals() || mesh->HasTangentsAndBitangents()) {
const aiMatrix3x3 m = aiMatrix3x3(mat).Inverse().Transpose();
if (mesh->HasNormals()) {
for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
mesh->mNormals[i] = (m * mesh->mNormals[i]).Normalize();
}
}
if (mesh->HasTangentsAndBitangents()) {
for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
mesh->mTangents[i] = (m * mesh->mTangents[i]).Normalize();
mesh->mBitangents[i] = (m * mesh->mBitangents[i]).Normalize();
}
mesh->mTangents[i] = (m * mesh->mTangents[i]).Normalize();
mesh->mBitangents[i] = (m * mesh->mBitangents[i]).Normalize();
}
}
}
@ -352,40 +350,41 @@ void PretransformVertices::BuildWCSMeshes(std::vector<aiMesh *> &out, aiMesh **i
// yes, we can.
mesh->mBones = reinterpret_cast<aiBone **>(&node->mTransformation);
mesh->mNumBones = UINT_MAX;
} else {
continue;
}
// try to find us in the list of newly created meshes
for (unsigned int n = 0; n < out.size(); ++n) {
aiMesh *ctz = out[n];
if (ctz->mNumBones == node->mMeshes[i] && *reinterpret_cast<aiMatrix4x4 *>(ctz->mBones) == node->mTransformation) {
// try to find us in the list of newly created meshes
for (unsigned int n = 0; n < out.size(); ++n) {
aiMesh *ctz = out[n];
if (ctz->mNumBones == node->mMeshes[i] && *reinterpret_cast<aiMatrix4x4 *>(ctz->mBones) == node->mTransformation) {
// ok, use this one. Update node mesh index
node->mMeshes[i] = numIn + n;
}
// ok, use this one. Update node mesh index
node->mMeshes[i] = numIn + n;
}
if (node->mMeshes[i] < numIn) {
// Worst case. Need to operate on a full copy of the mesh
ASSIMP_LOG_INFO("PretransformVertices: Copying mesh due to mismatching transforms");
aiMesh *ntz;
}
if (node->mMeshes[i] < numIn) {
// Worst case. Need to operate on a full copy of the mesh
ASSIMP_LOG_INFO("PretransformVertices: Copying mesh due to mismatching transforms");
aiMesh *ntz;
const unsigned int tmp = mesh->mNumBones; //
mesh->mNumBones = 0;
SceneCombiner::Copy(&ntz, mesh);
mesh->mNumBones = tmp;
const unsigned int cacheNumBones = mesh->mNumBones; //
mesh->mNumBones = 0;
SceneCombiner::Copy(&ntz, mesh);
mesh->mNumBones = cacheNumBones;
ntz->mNumBones = node->mMeshes[i];
ntz->mBones = reinterpret_cast<aiBone **>(&node->mTransformation);
ntz->mNumBones = node->mMeshes[i];
ntz->mBones = reinterpret_cast<aiBone **>(&node->mTransformation);
out.push_back(ntz);
out.push_back(ntz);
node->mMeshes[i] = static_cast<unsigned int>(numIn + out.size() - 1);
}
node->mMeshes[i] = static_cast<unsigned int>(numIn + out.size() - 1);
}
}
// call children
for (unsigned int i = 0; i < node->mNumChildren; ++i)
for (unsigned int i = 0; i < node->mNumChildren; ++i) {
BuildWCSMeshes(out, in, numIn, node->mChildren[i]);
}
}
// ------------------------------------------------------------------------------------------------
@ -394,8 +393,9 @@ void PretransformVertices::MakeIdentityTransform(aiNode *nd) const {
nd->mTransformation = aiMatrix4x4();
// call children
for (unsigned int i = 0; i < nd->mNumChildren; ++i)
for (unsigned int i = 0; i < nd->mNumChildren; ++i) {
MakeIdentityTransform(nd->mChildren[i]);
}
}
// ------------------------------------------------------------------------------------------------
@ -405,8 +405,27 @@ void PretransformVertices::BuildMeshRefCountArray(const aiNode *nd, unsigned int
refs[nd->mMeshes[i]]++;
// call children
for (unsigned int i = 0; i < nd->mNumChildren; ++i)
for (unsigned int i = 0; i < nd->mNumChildren; ++i) {
BuildMeshRefCountArray(nd->mChildren[i], refs);
}
}
// ------------------------------------------------------------------------------------------------
static void appendNewMeshesToScene(aiScene *pScene, std::vector<aiMesh*> &apcOutMeshes) {
ai_assert(pScene != nullptr);
if (apcOutMeshes.empty()) {
return;
}
aiMesh **npp = new aiMesh *[pScene->mNumMeshes + apcOutMeshes.size()];
::memcpy(npp, pScene->mMeshes, sizeof(aiMesh *) * pScene->mNumMeshes);
::memcpy(npp + pScene->mNumMeshes, &apcOutMeshes[0], sizeof(aiMesh *) * apcOutMeshes.size());
pScene->mNumMeshes += static_cast<unsigned int>(apcOutMeshes.size());
delete[] pScene->mMeshes;
pScene->mMeshes = npp;
}
// ------------------------------------------------------------------------------------------------
@ -418,12 +437,12 @@ void PretransformVertices::Execute(aiScene *pScene) {
if (!pScene->mNumMeshes)
return;
const unsigned int iOldMeshes = pScene->mNumMeshes;
const unsigned int iOldAnimationChannels = pScene->mNumAnimations;
const unsigned int iOldNodes = CountNodes(pScene->mRootNode);
const unsigned int oldMeshes = pScene->mNumMeshes;
const unsigned int oldAnimationChannels = pScene->mNumAnimations;
const unsigned int oldNodes = CountNodes(pScene->mRootNode);
if (configTransform) {
pScene->mRootNode->mTransformation = configTransformation * pScene->mRootNode->mTransformation;
if (mConfigTransform) {
pScene->mRootNode->mTransformation = mConfigTransformation * pScene->mRootNode->mTransformation;
}
// first compute absolute transformation matrices for all nodes
@ -449,22 +468,13 @@ void PretransformVertices::Execute(aiScene *pScene) {
// we go on and transform all meshes, if one is referenced by nodes
// with different absolute transformations a depth copy of the mesh
// is required.
if (configKeepHierarchy) {
if (mConfigKeepHierarchy) {
// Hack: store the matrix we're transforming a mesh with in aiMesh::mBones
BuildWCSMeshes(apcOutMeshes, pScene->mMeshes, pScene->mNumMeshes, pScene->mRootNode);
// ... if new meshes have been generated, append them to the end of the scene
if (apcOutMeshes.size() > 0) {
aiMesh **npp = new aiMesh *[pScene->mNumMeshes + apcOutMeshes.size()];
memcpy(npp, pScene->mMeshes, sizeof(aiMesh *) * pScene->mNumMeshes);
memcpy(npp + pScene->mNumMeshes, &apcOutMeshes[0], sizeof(aiMesh *) * apcOutMeshes.size());
pScene->mNumMeshes += static_cast<unsigned int>(apcOutMeshes.size());
delete[] pScene->mMeshes;
pScene->mMeshes = npp;
}
appendNewMeshesToScene(pScene, apcOutMeshes);
// now iterate through all meshes and transform them to world-space
for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) {
@ -488,34 +498,35 @@ void PretransformVertices::Execute(aiScene *pScene) {
aiVFormats.sort();
aiVFormats.unique();
for (std::list<unsigned int>::const_iterator j = aiVFormats.begin(); j != aiVFormats.end(); ++j) {
unsigned int iVertices = 0;
unsigned int iFaces = 0;
CountVerticesAndFaces(pScene, pScene->mRootNode, i, *j, &iFaces, &iVertices);
if (0 != iFaces && 0 != iVertices) {
unsigned int numVertices = 0u;
unsigned int numFaces = 0u;
CountVerticesAndFaces(pScene, pScene->mRootNode, i, *j, &numFaces, &numVertices);
if (0 != numFaces && 0 != numVertices) {
apcOutMeshes.push_back(new aiMesh());
aiMesh *pcMesh = apcOutMeshes.back();
pcMesh->mNumFaces = iFaces;
pcMesh->mNumVertices = iVertices;
pcMesh->mFaces = new aiFace[iFaces];
pcMesh->mVertices = new aiVector3D[iVertices];
pcMesh->mNumFaces = numFaces;
pcMesh->mNumVertices = numVertices;
pcMesh->mFaces = new aiFace[numFaces];
pcMesh->mVertices = new aiVector3D[numVertices];
pcMesh->mMaterialIndex = i;
if ((*j) & 0x2) pcMesh->mNormals = new aiVector3D[iVertices];
if ((*j) & 0x2) pcMesh->mNormals = new aiVector3D[numVertices];
if ((*j) & 0x4) {
pcMesh->mTangents = new aiVector3D[iVertices];
pcMesh->mBitangents = new aiVector3D[iVertices];
pcMesh->mTangents = new aiVector3D[numVertices];
pcMesh->mBitangents = new aiVector3D[numVertices];
}
iFaces = 0;
while ((*j) & (0x100 << iFaces)) {
pcMesh->mTextureCoords[iFaces] = new aiVector3D[iVertices];
if ((*j) & (0x10000 << iFaces))
pcMesh->mNumUVComponents[iFaces] = 3;
else
pcMesh->mNumUVComponents[iFaces] = 2;
iFaces++;
numFaces = 0;
while ((*j) & (0x100 << numFaces)) {
pcMesh->mTextureCoords[numFaces] = new aiVector3D[numVertices];
if ((*j) & (0x10000 << numFaces)) {
pcMesh->mNumUVComponents[numFaces] = 3;
} else {
pcMesh->mNumUVComponents[numFaces] = 2;
}
++numFaces;
}
iFaces = 0;
while ((*j) & (0x1000000 << iFaces))
pcMesh->mColors[iFaces++] = new aiColor4D[iVertices];
numFaces = 0;
while ((*j) & (0x1000000 << numFaces))
pcMesh->mColors[numFaces++] = new aiColor4D[numVertices];
// fill the mesh ...
unsigned int aiTemp[2] = { 0, 0 };
@ -593,7 +604,7 @@ void PretransformVertices::Execute(aiScene *pScene) {
l->mUp = aiMatrix3x3(nd->mTransformation) * l->mUp;
}
if (!configKeepHierarchy) {
if (!mConfigKeepHierarchy) {
// now delete all nodes in the scene and build a new
// flat node graph with a root node and some level 1 children
@ -644,7 +655,7 @@ void PretransformVertices::Execute(aiScene *pScene) {
MakeIdentityTransform(pScene->mRootNode);
}
if (configNormalize) {
if (mConfigNormalize) {
// compute the boundary of all meshes
aiVector3D min, max;
MinMaxChooser<aiVector3D>()(min, max);
@ -674,9 +685,9 @@ void PretransformVertices::Execute(aiScene *pScene) {
if (!DefaultLogger::isNullLogger()) {
ASSIMP_LOG_DEBUG("PretransformVerticesProcess finished");
ASSIMP_LOG_INFO("Removed ", iOldNodes, " nodes and ", iOldAnimationChannels, " animation channels (",
ASSIMP_LOG_INFO("Removed ", oldNodes, " nodes and ", oldAnimationChannels, " animation channels (",
CountNodes(pScene->mRootNode), " output nodes)");
ASSIMP_LOG_INFO("Kept ", pScene->mNumLights, " lights and ", pScene->mNumCameras, " cameras.");
ASSIMP_LOG_INFO("Moved ", iOldMeshes, " meshes to WCS (number of output meshes: ", pScene->mNumMeshes, ")");
ASSIMP_LOG_INFO("Moved ", oldMeshes, " meshes to WCS (number of output meshes: ", pScene->mNumMeshes, ")");
}
}

View File

@ -90,7 +90,7 @@ public:
* @param keep true for keep configuration.
*/
void KeepHierarchy(bool keep) {
configKeepHierarchy = keep;
mConfigKeepHierarchy = keep;
}
// -------------------------------------------------------------------
@ -98,7 +98,7 @@ public:
* @return ...
*/
bool IsHierarchyKept() const {
return configKeepHierarchy;
return mConfigKeepHierarchy;
}
private:
@ -108,7 +108,7 @@ private:
// -------------------------------------------------------------------
// Get a bitwise combination identifying the vertex format of a mesh
unsigned int GetMeshVFormat(aiMesh *pcMesh) const;
//unsigned int GetMeshVFormat(aiMesh *pcMesh) const;
// -------------------------------------------------------------------
// Count the number of vertices in the whole scene and a given
@ -131,8 +131,8 @@ private:
// -------------------------------------------------------------------
// Get a list of all vertex formats that occur for a given material
// The output list contains duplicate elements
void GetVFormatList(const aiScene *pcScene, unsigned int iMat,
std::list<unsigned int> &aiOut) const;
/*void GetVFormatList(const aiScene *pcScene, unsigned int iMat,
std::list<unsigned int> &aiOut) const;*/
// -------------------------------------------------------------------
// Compute the absolute transformation matrices of each node
@ -156,10 +156,10 @@ private:
void BuildMeshRefCountArray(const aiNode *nd, unsigned int *refs) const;
//! Configuration option: keep scene hierarchy as long as possible
bool configKeepHierarchy;
bool configNormalize;
bool configTransform;
aiMatrix4x4 configTransformation;
bool mConfigKeepHierarchy;
bool mConfigNormalize;
bool mConfigTransform;
aiMatrix4x4 mConfigTransformation;
bool mConfigPointCloud;
};

View File

@ -175,10 +175,9 @@ unsigned int GetMeshVFormatUnique(const aiMesh *pcMesh) {
// tangents and bitangents
if (pcMesh->HasTangentsAndBitangents()) iRet |= 0x4;
#ifdef BOOST_STATIC_ASSERT
BOOST_STATIC_ASSERT(8 >= AI_MAX_NUMBER_OF_COLOR_SETS);
BOOST_STATIC_ASSERT(8 >= AI_MAX_NUMBER_OF_TEXTURECOORDS);
#endif
static_assert(8 >= AI_MAX_NUMBER_OF_COLOR_SETS);
static_assert(8 >= AI_MAX_NUMBER_OF_TEXTURECOORDS);
// texture coordinates
unsigned int p = 0;

View File

@ -5,8 +5,6 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2022, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
@ -45,7 +43,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
// internal headers
#include "RemoveRedundantMaterials.h"
#include <assimp/ParsingUtils.h>
#include "ProcessHelper.h"
@ -57,35 +54,28 @@ using namespace Assimp;
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
RemoveRedundantMatsProcess::RemoveRedundantMatsProcess()
: mConfigFixedMaterials() {
// nothing to do here
}
RemoveRedundantMatsProcess::RemoveRedundantMatsProcess() : mConfigFixedMaterials() {}
// ------------------------------------------------------------------------------------------------
// Returns whether the processing step is present in the given flag field.
bool RemoveRedundantMatsProcess::IsActive( unsigned int pFlags) const
{
bool RemoveRedundantMatsProcess::IsActive( unsigned int pFlags) const {
return (pFlags & aiProcess_RemoveRedundantMaterials) != 0;
}
// ------------------------------------------------------------------------------------------------
// Setup import properties
void RemoveRedundantMatsProcess::SetupProperties(const Importer* pImp)
{
void RemoveRedundantMatsProcess::SetupProperties(const Importer* pImp) {
// Get value of AI_CONFIG_PP_RRM_EXCLUDE_LIST
mConfigFixedMaterials = pImp->GetPropertyString(AI_CONFIG_PP_RRM_EXCLUDE_LIST,"");
}
// ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported data.
void RemoveRedundantMatsProcess::Execute( aiScene* pScene)
{
void RemoveRedundantMatsProcess::Execute( aiScene* pScene) {
ASSIMP_LOG_DEBUG("RemoveRedundantMatsProcess begin");
unsigned int redundantRemoved = 0, unreferencedRemoved = 0;
if (pScene->mNumMaterials)
{
if (pScene->mNumMaterials) {
// Find out which materials are referenced by meshes
std::vector<bool> abReferenced(pScene->mNumMaterials,false);
for (unsigned int i = 0;i < pScene->mNumMeshes;++i)
@ -134,8 +124,7 @@ void RemoveRedundantMatsProcess::Execute( aiScene* pScene)
// we do already have a specific hash. This allows us to
// determine which materials are identical.
uint32_t *aiHashes = new uint32_t[ pScene->mNumMaterials ];;
for (unsigned int i = 0; i < pScene->mNumMaterials;++i)
{
for (unsigned int i = 0; i < pScene->mNumMaterials;++i) {
// No mesh is referencing this material, remove it.
if (!abReferenced[i]) {
++unreferencedRemoved;
@ -147,8 +136,7 @@ void RemoveRedundantMatsProcess::Execute( aiScene* pScene)
// Check all previously mapped materials for a matching hash.
// On a match we can delete this material and just make it ref to the same index.
uint32_t me = aiHashes[i] = ComputeMaterialHash(pScene->mMaterials[i]);
for (unsigned int a = 0; a < i;++a)
{
for (unsigned int a = 0; a < i;++a) {
if (abReferenced[a] && me == aiHashes[a]) {
++redundantRemoved;
me = 0;
@ -205,12 +193,9 @@ void RemoveRedundantMatsProcess::Execute( aiScene* pScene)
delete[] aiHashes;
delete[] aiMappingTable;
}
if (redundantRemoved == 0 && unreferencedRemoved == 0)
{
if (redundantRemoved == 0 && unreferencedRemoved == 0) {
ASSIMP_LOG_DEBUG("RemoveRedundantMatsProcess finished ");
}
else
{
} else {
ASSIMP_LOG_INFO("RemoveRedundantMatsProcess finished. Removed ", redundantRemoved, " redundant and ",
unreferencedRemoved, " unused materials.");
}

View File

@ -5,8 +5,6 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2022, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
@ -74,63 +72,6 @@ inline void ArrayDelete(T **&in, unsigned int &num) {
num = 0;
}
#if 0
// ------------------------------------------------------------------------------------------------
// Updates the node graph - removes all nodes which have the "remove" flag set and the
// "don't remove" flag not set. Nodes with meshes are never deleted.
bool UpdateNodeGraph(aiNode* node,std::list<aiNode*>& childsOfParent,bool root)
{
bool b = false;
std::list<aiNode*> mine;
for (unsigned int i = 0; i < node->mNumChildren;++i)
{
if(UpdateNodeGraph(node->mChildren[i],mine,false))
b = true;
}
// somewhat tricky ... mNumMeshes must be originally 0 and MSB2 may not be set,
// so we can do a simple comparison against MSB here
if (!root && AI_RC_UINT_MSB == node->mNumMeshes )
{
// this node needs to be removed
if(node->mNumChildren)
{
childsOfParent.insert(childsOfParent.end(),mine.begin(),mine.end());
// set all children to nullptr to make sure they are not deleted when we delete ourself
for (unsigned int i = 0; i < node->mNumChildren;++i)
node->mChildren[i] = nullptr;
}
b = true;
delete node;
}
else
{
AI_RC_UNMASK(node->mNumMeshes);
childsOfParent.push_back(node);
if (b)
{
// reallocate the array of our children here
node->mNumChildren = (unsigned int)mine.size();
aiNode** const children = new aiNode*[mine.size()];
aiNode** ptr = children;
for (std::list<aiNode*>::iterator it = mine.begin(), end = mine.end();
it != end; ++it)
{
*ptr++ = *it;
}
delete[] node->mChildren;
node->mChildren = children;
return false;
}
}
return b;
}
#endif
// ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported data.
void RemoveVCProcess::Execute(aiScene *pScene) {

View File

@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2022, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
@ -86,9 +85,9 @@ void ScaleProcess::Execute( aiScene* pScene ) {
return; // nothing to scale
}
ai_assert( mScale != 0 );
ai_assert( nullptr != pScene );
ai_assert( nullptr != pScene->mRootNode );
ai_assert(mScale != 0 );
ai_assert(nullptr != pScene );
ai_assert(nullptr != pScene->mRootNode );
if ( nullptr == pScene ) {
return;
@ -140,7 +139,7 @@ void ScaleProcess::Execute( aiScene* pScene ) {
aiMatrix4x4 scaling;
aiMatrix4x4::Scaling( aiVector3D(scale), scaling );
aiMatrix4x4 RotMatrix = aiMatrix4x4 (rotation.GetMatrix());
const aiMatrix4x4 RotMatrix = aiMatrix4x4(rotation.GetMatrix());
bone->mOffsetMatrix = translation * RotMatrix * scaling;
}

View File

@ -5,8 +5,6 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2022, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
@ -54,10 +52,7 @@ using namespace Assimp;
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
SortByPTypeProcess::SortByPTypeProcess() :
mConfigRemoveMeshes(0) {
// empty
}
SortByPTypeProcess::SortByPTypeProcess() : mConfigRemoveMeshes(0) {}
// ------------------------------------------------------------------------------------------------
// Returns whether the processing step is present in the given flag field.
@ -104,8 +99,9 @@ void UpdateNodes(const std::vector<unsigned int> &replaceMeshIndex, aiNode *node
}
// call all subnodes recursively
for (unsigned int m = 0; m < node->mNumChildren; ++m)
for (unsigned int m = 0; m < node->mNumChildren; ++m) {
UpdateNodes(replaceMeshIndex, node->mChildren[m]);
}
}
// ------------------------------------------------------------------------------------------------
@ -155,7 +151,7 @@ void SortByPTypeProcess::Execute(aiScene *pScene) {
if (1 == num) {
if (!(mConfigRemoveMeshes & mesh->mPrimitiveTypes)) {
*meshIdx = static_cast<unsigned int>(outMeshes.size());
outMeshes.push_back(mesh);
outMeshes.emplace_back(mesh);
} else {
delete mesh;
pScene->mMeshes[i] = nullptr;
@ -311,21 +307,23 @@ void SortByPTypeProcess::Execute(aiScene *pScene) {
if (vert) {
*vert++ = mesh->mVertices[idx];
//mesh->mVertices[idx].x = get_qnan();
}
if (nor) *nor++ = mesh->mNormals[idx];
if (nor)
*nor++ = mesh->mNormals[idx];
if (tan) {
*tan++ = mesh->mTangents[idx];
*bit++ = mesh->mBitangents[idx];
}
for (unsigned int pp = 0; pp < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++pp) {
if (!uv[pp]) break;
if (!uv[pp])
break;
*uv[pp]++ = mesh->mTextureCoords[pp][idx];
}
for (unsigned int pp = 0; pp < AI_MAX_NUMBER_OF_COLOR_SETS; ++pp) {
if (!cols[pp]) break;
if (!cols[pp])
break;
*cols[pp]++ = mesh->mColors[pp][idx];
}
@ -351,7 +349,7 @@ void SortByPTypeProcess::Execute(aiScene *pScene) {
}
}
if (pp == mesh->mNumAnimMeshes)
amIdx++;
++amIdx;
in.mIndices[q] = outIdx++;
}

View File

@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2022, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
@ -58,9 +57,7 @@ using namespace Assimp::Formatter;
// ------------------------------------------------------------------------------------------------
// Constructor
SplitByBoneCountProcess::SplitByBoneCountProcess() : mMaxBoneCount(AI_SBBC_DEFAULT_MAX_BONES) {
// empty
}
SplitByBoneCountProcess::SplitByBoneCountProcess() : mMaxBoneCount(AI_SBBC_DEFAULT_MAX_BONES) {}
// ------------------------------------------------------------------------------------------------
// Returns whether the processing step is present in the given flag.
@ -166,7 +163,7 @@ void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vector<aiMesh
unsigned int numBones = 0;
std::vector<bool> isBoneUsed( pMesh->mNumBones, false);
// indices of the faces which are going to go into this submesh
std::vector<unsigned int> subMeshFaces;
IndexArray subMeshFaces;
subMeshFaces.reserve( pMesh->mNumFaces);
// accumulated vertex count of all the faces in this submesh
unsigned int numSubMeshVertices = 0;
@ -202,7 +199,7 @@ void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vector<aiMesh
for (std::set<unsigned int>::iterator it = newBonesAtCurrentFace.begin(); it != newBonesAtCurrentFace.end(); ++it) {
if (!isBoneUsed[*it]) {
isBoneUsed[*it] = true;
numBones++;
++numBones;
}
}
@ -212,18 +209,17 @@ void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vector<aiMesh
// remember that this face is handled
isFaceHandled[a] = true;
numFacesHandled++;
++numFacesHandled;
}
// create a new mesh to hold this subset of the source mesh
aiMesh* newMesh = new aiMesh;
if( pMesh->mName.length > 0 )
{
if( pMesh->mName.length > 0 ) {
newMesh->mName.Set( format() << pMesh->mName.data << "_sub" << poNewMeshes.size());
}
newMesh->mMaterialIndex = pMesh->mMaterialIndex;
newMesh->mPrimitiveTypes = pMesh->mPrimitiveTypes;
poNewMeshes.push_back( newMesh);
poNewMeshes.emplace_back( newMesh);
// create all the arrays for this mesh if the old mesh contained them
newMesh->mNumVertices = numSubMeshVertices;
@ -251,7 +247,7 @@ void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vector<aiMesh
// and copy over the data, generating faces with linear indices along the way
newMesh->mFaces = new aiFace[subMeshFaces.size()];
unsigned int nvi = 0; // next vertex index
std::vector<unsigned int> previousVertexIndices( numSubMeshVertices, std::numeric_limits<unsigned int>::max()); // per new vertex: its index in the source mesh
IndexArray previousVertexIndices( numSubMeshVertices, std::numeric_limits<unsigned int>::max()); // per new vertex: its index in the source mesh
for( unsigned int a = 0; a < subMeshFaces.size(); ++a ) {
const aiFace& srcFace = pMesh->mFaces[subMeshFaces[a]];
aiFace& dstFace = newMesh->mFaces[a];
@ -399,10 +395,10 @@ void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vector<aiMesh
void SplitByBoneCountProcess::UpdateNode( aiNode* pNode) const {
// rebuild the node's mesh index list
if( pNode->mNumMeshes == 0 ) {
std::vector<unsigned int> newMeshList;
IndexArray newMeshList;
for( unsigned int a = 0; a < pNode->mNumMeshes; ++a) {
unsigned int srcIndex = pNode->mMeshes[a];
const std::vector<unsigned int>& replaceMeshes = mSubMeshIndices[srcIndex];
const IndexArray& replaceMeshes = mSubMeshIndices[srcIndex];
newMeshList.insert( newMeshList.end(), replaceMeshes.begin(), replaceMeshes.end());
}

View File

@ -76,6 +76,10 @@ public:
/// basing on the Importer's configuration property list.
virtual void SetupProperties(const Importer* pImp) override;
/// @brief Will return the maximal number of bones.
/// @return The maximal number of bones.
size_t getMaxNumberOfBones() const;
protected:
/// Executes the post processing step on the given imported data.
/// At the moment a process is not supposed to fail.
@ -90,14 +94,19 @@ protected:
/// Recursively updates the node's mesh list to account for the changed mesh list
void UpdateNode( aiNode* pNode) const;
public:
private:
/// Max bone count. Splitting occurs if a mesh has more than that number of bones.
size_t mMaxBoneCount;
/// Per mesh index: Array of indices of the new submeshes.
std::vector< std::vector<unsigned int> > mSubMeshIndices;
using IndexArray = std::vector<unsigned int>;
std::vector<IndexArray> mSubMeshIndices;
};
inline size_t SplitByBoneCountProcess::getMaxNumberOfBones() const {
return mMaxBoneCount;
}
} // end of namespace Assimp
#endif // !!AI_SPLITBYBONECOUNTPROCESS_H_INC

View File

@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2022, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
@ -40,9 +39,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
/**
* @file Implementation of the SplitLargeMeshes postprocessing step
*/
/// @file Implementation of the SplitLargeMeshes postprocessing step
// internal headers of the post-processing framework
#include "SplitLargeMeshes.h"
@ -75,22 +72,22 @@ void SplitLargeMeshesProcess_Triangle::Execute( aiScene* pScene) {
this->SplitMesh(a, pScene->mMeshes[a],avList);
}
if (avList.size() != pScene->mNumMeshes) {
// it seems something has been split. rebuild the mesh list
delete[] pScene->mMeshes;
pScene->mNumMeshes = (unsigned int)avList.size();
pScene->mMeshes = new aiMesh*[avList.size()];
for (unsigned int i = 0; i < avList.size();++i) {
pScene->mMeshes[i] = avList[i].first;
}
// now we need to update all nodes
this->UpdateNode(pScene->mRootNode,avList);
ASSIMP_LOG_INFO("SplitLargeMeshesProcess_Triangle finished. Meshes have been split");
} else {
if (avList.size() == pScene->mNumMeshes) {
ASSIMP_LOG_DEBUG("SplitLargeMeshesProcess_Triangle finished. There was nothing to do");
}
// it seems something has been split. rebuild the mesh list
delete[] pScene->mMeshes;
pScene->mNumMeshes = (unsigned int)avList.size();
pScene->mMeshes = new aiMesh*[avList.size()];
for (unsigned int i = 0; i < avList.size();++i) {
pScene->mMeshes[i] = avList[i].first;
}
// now we need to update all nodes
this->UpdateNode(pScene->mRootNode,avList);
ASSIMP_LOG_INFO("SplitLargeMeshesProcess_Triangle finished. Meshes have been split");
}
// ------------------------------------------------------------------------------------------------
@ -102,8 +99,7 @@ void SplitLargeMeshesProcess_Triangle::SetupProperties( const Importer* pImp) {
// ------------------------------------------------------------------------------------------------
// Update a node after some meshes have been split
void SplitLargeMeshesProcess_Triangle::UpdateNode(aiNode* pcNode,
const std::vector<std::pair<aiMesh*, unsigned int> >& avList) {
void SplitLargeMeshesProcess_Triangle::UpdateNode(aiNode* pcNode, const std::vector<std::pair<aiMesh*, unsigned int> >& avList) {
// for every index in out list build a new entry
std::vector<unsigned int> aiEntries;
aiEntries.reserve(pcNode->mNumMeshes + 1);

View File

@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2022, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
@ -42,8 +41,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/** @file A helper class that processes texture transformations */
#include <assimp/Importer.hpp>
#include <assimp/postprocess.h>
#include <assimp/DefaultLogger.hpp>
@ -494,8 +491,9 @@ void TextureTransformStep::Execute( aiScene* pScene) {
ai_assert(nullptr != src);
// Copy the data to the destination array
if (dest != src)
if (dest != src) {
::memcpy(dest,src,sizeof(aiVector3D)*mesh->mNumVertices);
}
end = dest + mesh->mNumVertices;

View File

@ -158,15 +158,13 @@ namespace {
// ------------------------------------------------------------------------------------------------
// Returns whether the processing step is present in the given flag field.
bool TriangulateProcess::IsActive( unsigned int pFlags) const
{
bool TriangulateProcess::IsActive( unsigned int pFlags) const {
return (pFlags & aiProcess_Triangulate) != 0;
}
// ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported data.
void TriangulateProcess::Execute( aiScene* pScene)
{
void TriangulateProcess::Execute( aiScene* pScene) {
ASSIMP_LOG_DEBUG("TriangulateProcess begin");
bool bHas = false;
@ -187,8 +185,7 @@ void TriangulateProcess::Execute( aiScene* pScene)
// ------------------------------------------------------------------------------------------------
// Triangulates the given mesh.
bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh)
{
bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh) {
// Now we have aiMesh::mPrimitiveTypes, so this is only here for test cases
if (!pMesh->mPrimitiveTypes) {
bool bNeed = false;
@ -218,8 +215,7 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh)
if( face.mNumIndices <= 3) {
numOut++;
}
else {
} else {
numOut += face.mNumIndices-2;
max_out = std::max(max_out,face.mNumIndices);
}
@ -511,22 +507,6 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh)
#endif
num = 0;
break;
/*curOut -= (max-num); // undo all previous work
for (tmp = 0; tmp < max-2; ++tmp) {
aiFace& nface = *curOut++;
nface.mNumIndices = 3;
if (!nface.mIndices)
nface.mIndices = new unsigned int[3];
nface.mIndices[0] = 0;
nface.mIndices[1] = tmp+1;
nface.mIndices[2] = tmp+2;
}
num = 0;
break;*/
}
aiFace& nface = *curOut++;
@ -580,23 +560,6 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh)
for(aiFace* f = last_face; f != curOut; ) {
unsigned int* i = f->mIndices;
// drop dumb 0-area triangles - deactivated for now:
//FindDegenerates post processing step can do the same thing
//if (std::fabs(GetArea2D(temp_verts[i[0]],temp_verts[i[1]],temp_verts[i[2]])) < 1e-5f) {
// ASSIMP_LOG_VERBOSE_DEBUG("Dropping triangle with area 0");
// --curOut;
// delete[] f->mIndices;
// f->mIndices = nullptr;
// for(aiFace* ff = f; ff != curOut; ++ff) {
// ff->mNumIndices = (ff+1)->mNumIndices;
// ff->mIndices = (ff+1)->mIndices;
// (ff+1)->mIndices = nullptr;
// }
// continue;
//}
i[0] = idx[i[0]];
i[1] = idx[i[1]];
i[2] = idx[i[2]];

View File

@ -5,8 +5,6 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2022, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
@ -110,18 +108,21 @@ inline int HasNameMatch(const aiString &in, aiNode *node) {
template <typename T>
inline void ValidateDSProcess::DoValidation(T **parray, unsigned int size, const char *firstName, const char *secondName) {
// validate all entries
if (size) {
if (!parray) {
ReportError("aiScene::%s is nullptr (aiScene::%s is %i)",
firstName, secondName, size);
}
for (unsigned int i = 0; i < size; ++i) {
if (!parray[i]) {
ReportError("aiScene::%s[%i] is nullptr (aiScene::%s is %i)",
firstName, i, secondName, size);
}
Validate(parray[i]);
if (size == 0) {
return;
}
if (!parray) {
ReportError("aiScene::%s is nullptr (aiScene::%s is %i)",
firstName, secondName, size);
}
for (unsigned int i = 0; i < size; ++i) {
if (!parray[i]) {
ReportError("aiScene::%s[%i] is nullptr (aiScene::%s is %i)",
firstName, i, secondName, size);
}
Validate(parray[i]);
}
}
@ -130,25 +131,27 @@ template <typename T>
inline void ValidateDSProcess::DoValidationEx(T **parray, unsigned int size,
const char *firstName, const char *secondName) {
// validate all entries
if (size) {
if (!parray) {
ReportError("aiScene::%s is nullptr (aiScene::%s is %i)",
firstName, secondName, size);
if (size == 0) {
return;
}
if (!parray) {
ReportError("aiScene::%s is nullptr (aiScene::%s is %i)",
firstName, secondName, size);
}
for (unsigned int i = 0; i < size; ++i) {
if (!parray[i]) {
ReportError("aiScene::%s[%u] is nullptr (aiScene::%s is %u)",
firstName, i, secondName, size);
}
for (unsigned int i = 0; i < size; ++i) {
if (!parray[i]) {
ReportError("aiScene::%s[%u] is nullptr (aiScene::%s is %u)",
firstName, i, secondName, size);
}
Validate(parray[i]);
Validate(parray[i]);
// check whether there are duplicate names
for (unsigned int a = i + 1; a < size; ++a) {
if (parray[i]->mName == parray[a]->mName) {
ReportError("aiScene::%s[%u] has the same name as "
"aiScene::%s[%u]",
firstName, i, secondName, a);
}
// check whether there are duplicate names
for (unsigned int a = i + 1; a < size; ++a) {
if (parray[i]->mName == parray[a]->mName) {
ReportError("aiScene::%s[%u] has the same name as "
"aiScene::%s[%u]",
firstName, i, secondName, a);
}
}
}
@ -229,12 +232,6 @@ void ValidateDSProcess::Execute(aiScene *pScene) {
if (pScene->mNumMaterials) {
DoValidation(pScene->mMaterials, pScene->mNumMaterials, "mMaterials", "mNumMaterials");
}
#if 0
// NOTE: ScenePreprocessor generates a default material if none is there
else if (!(mScene->mFlags & AI_SCENE_FLAGS_INCOMPLETE)) {
ReportError("aiScene::mNumMaterials is 0. At least one material must be there");
}
#endif
else if (pScene->mMaterials) {
ReportError("aiScene::mMaterials is non-null although there are no materials");
}
@ -267,8 +264,7 @@ void ValidateDSProcess::Validate(const aiCamera *pCamera) {
if (pCamera->mClipPlaneFar <= pCamera->mClipPlaneNear)
ReportError("aiCamera::mClipPlaneFar must be >= aiCamera::mClipPlaneNear");
// FIX: there are many 3ds files with invalid FOVs. No reason to
// reject them at all ... a warning is appropriate.
// There are many 3ds files with invalid FOVs. No reason to reject them at all ... a warning is appropriate.
if (!pCamera->mHorizontalFOV || pCamera->mHorizontalFOV >= (float)AI_MATH_PI)
ReportWarning("%f is not a valid value for aiCamera::mHorizontalFOV", pCamera->mHorizontalFOV);
}
@ -290,7 +286,6 @@ void ValidateDSProcess::Validate(const aiMesh *pMesh) {
switch (face.mNumIndices) {
case 0:
ReportError("aiMesh::mFaces[%i].mNumIndices is 0", i);
break;
case 1:
if (0 == (pMesh->mPrimitiveTypes & aiPrimitiveType_POINT)) {
ReportError("aiMesh::mFaces[%i] is a POINT but aiMesh::mPrimitiveTypes "
@ -362,15 +357,6 @@ void ValidateDSProcess::Validate(const aiMesh *pMesh) {
if (face.mIndices[a] >= pMesh->mNumVertices) {
ReportError("aiMesh::mFaces[%i]::mIndices[%i] is out of range", i, a);
}
// the MSB flag is temporarily used by the extra verbose
// mode to tell us that the JoinVerticesProcess might have
// been executed already.
/*if ( !(this->mScene->mFlags & AI_SCENE_FLAGS_NON_VERBOSE_FORMAT ) && !(this->mScene->mFlags & AI_SCENE_FLAGS_ALLOW_SHARED) &&
abRefList[face.mIndices[a]])
{
ReportError("aiMesh::mVertices[%i] is referenced twice - second "
"time by aiMesh::mFaces[%i]::mIndices[%i]",face.mIndices[a],i,a);
}*/
abRefList[face.mIndices[a]] = true;
}
}
@ -466,7 +452,7 @@ void ValidateDSProcess::Validate(const aiMesh *pMesh, const aiBone *pBone, float
this->Validate(&pBone->mName);
if (!pBone->mNumWeights) {
//ReportError("aiBone::mNumWeights is zero");
ReportWarning("aiBone::mNumWeights is zero");
}
// check whether all vertices affected by this bone are valid

View File

@ -92,6 +92,7 @@ namespace o3dgc
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// - - Static functions - - - - - - - - - - - - - - - - - - - - - - - - - - -
AI_WONT_RETURN static void AC_Error(const char * msg) AI_WONT_RETURN_SUFFIX;
static void AC_Error(const char * msg)
{
fprintf(stderr, "\n\n -> Arithmetic coding error: ");

View File

@ -78,7 +78,7 @@
# pragma warning(disable : 4131 4244 4189 4245)
#endif // _MSC_VER
const char unz_copyright[] =
static const char unz_copyright[] =
" unzip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll";
/* unz_file_info_internal contain internal info about a file in zipfile*/

View File

@ -40,6 +40,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <assimp/cimport.h>
#include <assimp/Importer.hpp>
#include <assimp/Exporter.hpp>
#include <assimp/scene.h>
#include <assimp/postprocess.h>
@ -53,6 +54,13 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t dataSize) {
const aiScene *sc = importer.ReadFileFromMemory(data, dataSize,
aiProcessPreset_TargetRealtime_Quality, nullptr );
if (sc == nullptr) {
return 0;
}
Exporter exporter;
exporter.ExportToBlob(sc, "fbx");
aiDetachLogStream(&stream);
return 0;

View File

@ -66,7 +66,7 @@ ASSIMP_API void setAiAssertHandler(AiAssertHandler handler);
*
* @brief This issues a message to stderr and calls abort.
*/
ASSIMP_API void defaultAiAssertHandler(const char* failedExpression, const char* file, int line);
AI_WONT_RETURN ASSIMP_API void defaultAiAssertHandler(const char* failedExpression, const char* file, int line) AI_WONT_RETURN_SUFFIX;
// ---------------------------------------------------------------------------
/**

View File

@ -84,7 +84,7 @@ protected:
public:
/** Destructor public to allow simple deletion to close the file. */
~DefaultIOStream ();
~DefaultIOStream () override;
// -------------------------------------------------------------------
/// Read from stream

View File

@ -65,8 +65,8 @@ namespace Assimp {
// ----------------------------------------------------------------------------------
class MemoryIOStream : public IOStream {
public:
MemoryIOStream (const uint8_t* buff, size_t len, bool own = false) :
buffer (buff),
MemoryIOStream (const uint8_t* buff, size_t len, bool own = false) :
buffer (buff),
length(len),
pos(static_cast<size_t>(0)),
own(own) {
@ -145,7 +145,7 @@ public:
}
/// @brief Destructor.
~MemoryIOSystem() = default;
~MemoryIOSystem() override = default;
// -------------------------------------------------------------------
/// @brief Tests for the existence of a file at the given path.
@ -190,7 +190,7 @@ public:
bool ComparePaths(const char* one, const char* second) const override {
return existing_io ? existing_io->ComparePaths(one, second) : false;
}
/// @brief Will push the directory.
bool PushDirectory( const std::string &path ) override {
return existing_io ? existing_io->PushDirectory(path) : false;
@ -216,7 +216,7 @@ public:
bool CreateDirectory( const std::string &path ) override {
return existing_io ? existing_io->CreateDirectory(path) : false;
}
/// @brief Will change the directory.
bool ChangeDirectory( const std::string &path ) override {
return existing_io ? existing_io->ChangeDirectory(path) : false;

View File

@ -5,8 +5,6 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2022, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
@ -68,8 +66,7 @@ namespace Assimp {
*/
// --------------------------------------------------------------------------------------------
template <bool SwapEndianess = false, bool RuntimeSwitch = false>
class StreamWriter
{
class StreamWriter {
enum {
INITIAL_CAPACITY = 1024
};

View File

@ -97,15 +97,21 @@ namespace Assimp {
* to *all* vertex components equally. This is useful for stuff like interpolation
* or subdivision, but won't work if special handling is required for some vertex components. */
// ------------------------------------------------------------------------------------------------
class Vertex {
struct Vertex {
friend Vertex operator + (const Vertex&,const Vertex&);
friend Vertex operator - (const Vertex&,const Vertex&);
friend Vertex operator * (const Vertex&,ai_real);
friend Vertex operator / (const Vertex&,ai_real);
friend Vertex operator * (ai_real, const Vertex&);
public:
Vertex() {}
aiVector3D position;
aiVector3D normal;
aiVector3D tangent, bitangent;
aiVector3D texcoords[AI_MAX_NUMBER_OF_TEXTURECOORDS];
aiColor4D colors[AI_MAX_NUMBER_OF_COLOR_SETS];
Vertex() = default;
// ----------------------------------------------------------------------------
/** Extract a particular vertex from a mesh and interleave all components */
@ -178,7 +184,7 @@ public:
}
// ----------------------------------------------------------------------------
/** Convert back to non-interleaved storage */
/// Convert back to non-interleaved storage
void SortBack(aiMesh* out, unsigned int idx) const {
ai_assert(idx<out->mNumVertices);
out->mVertices[idx] = position;
@ -204,7 +210,7 @@ public:
private:
// ----------------------------------------------------------------------------
/** Construct from two operands and a binary operation to combine them */
/// Construct from two operands and a binary operation to combine them
template <template <typename t> class op> static Vertex BinaryOp(const Vertex& v0, const Vertex& v1) {
// this is a heavy task for the compiler to optimize ... *pray*
@ -224,7 +230,7 @@ private:
}
// ----------------------------------------------------------------------------
/** This time binary arithmetic of v0 with a floating-point number */
/// This time binary arithmetic of v0 with a floating-point number
template <template <typename, typename, typename> class op> static Vertex BinaryOp(const Vertex& v0, ai_real f) {
// this is a heavy task for the compiler to optimize ... *pray*
@ -262,15 +268,6 @@ private:
}
return res;
}
public:
aiVector3D position;
aiVector3D normal;
aiVector3D tangent, bitangent;
aiVector3D texcoords[AI_MAX_NUMBER_OF_TEXTURECOORDS];
aiColor4D colors[AI_MAX_NUMBER_OF_COLOR_SETS];
};
// ------------------------------------------------------------------------------------------------

View File

@ -63,7 +63,7 @@ public:
//! Open a Zip using the proffered IOSystem
ZipArchiveIOSystem(IOSystem* pIOHandler, const char *pFilename, const char* pMode = "r");
ZipArchiveIOSystem(IOSystem* pIOHandler, const std::string& rFilename, const char* pMode = "r");
virtual ~ZipArchiveIOSystem();
virtual ~ZipArchiveIOSystem() override;
bool Exists(const char* pFilename) const override;
char getOsSeparator() const override;
IOStream* Open(const char* pFilename, const char* pMode = "rb") override;

View File

@ -184,6 +184,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifdef __GNUC__
# define AI_WONT_RETURN_SUFFIX __attribute__((noreturn))
#elif _MSC_VER
#if defined(__clang__)
# define AI_WONT_RETURN_SUFFIX __attribute__((noreturn))
#else
# define AI_WONT_RETURN_SUFFIX
#endif
#else
# define AI_WONT_RETURN_SUFFIX
#endif // (defined __clang__)
@ -283,7 +289,11 @@ typedef unsigned int ai_uint;
#define AI_RAD_TO_DEG(x) ((x) * (ai_real) 57.2957795)
/* Numerical limits */
static const ai_real ai_epsilon = (ai_real) 1e-6;
#ifdef __cplusplus
constexpr ai_real ai_epsilon = (ai_real) 1e-6;
#else
const ai_real ai_epsilon = (ai_real) 1e-6;
#endif
/* Support for big-endian builds */
#if defined(__BYTE_ORDER__)

View File

@ -39,7 +39,9 @@
namespace Assimp {
const double fast_atof_table[16] = { // we write [16] here instead of [] to work around a swig bug
static constexpr size_t NumItems = 16;
constexpr double fast_atof_table[NumItems] = { // we write [16] here instead of [] to work around a swig bug
0.0,
0.1,
0.01,
@ -58,12 +60,10 @@ const double fast_atof_table[16] = { // we write [16] here instead of [] to wo
0.000000000000001
};
// ------------------------------------------------------------------------------------
// Convert a string in decimal format to a number
// ------------------------------------------------------------------------------------
inline
unsigned int strtoul10( const char* in, const char** out=0) {
inline unsigned int strtoul10( const char* in, const char** out=0) {
unsigned int value = 0;
for ( ;; ) {
@ -83,8 +83,7 @@ unsigned int strtoul10( const char* in, const char** out=0) {
// ------------------------------------------------------------------------------------
// Convert a string in octal format to a number
// ------------------------------------------------------------------------------------
inline
unsigned int strtoul8( const char* in, const char** out=0) {
inline unsigned int strtoul8( const char* in, const char** out=0) {
unsigned int value( 0 );
for ( ;; ) {
if ( *in < '0' || *in > '7' ) {
@ -103,8 +102,7 @@ unsigned int strtoul8( const char* in, const char** out=0) {
// ------------------------------------------------------------------------------------
// Convert a string in hex format to a number
// ------------------------------------------------------------------------------------
inline
unsigned int strtoul16( const char* in, const char** out=0) {
inline unsigned int strtoul16( const char* in, const char** out=0) {
unsigned int value( 0 );
for ( ;; ) {
if ( *in >= '0' && *in <= '9' ) {
@ -128,8 +126,7 @@ unsigned int strtoul16( const char* in, const char** out=0) {
// Convert just one hex digit
// Return value is UINT_MAX if the input character is not a hex digit.
// ------------------------------------------------------------------------------------
inline
unsigned int HexDigitToDecimal(char in) {
inline unsigned int HexDigitToDecimal(char in) {
unsigned int out( UINT_MAX );
if ( in >= '0' && in <= '9' ) {
out = in - '0';
@ -146,16 +143,14 @@ unsigned int HexDigitToDecimal(char in) {
// ------------------------------------------------------------------------------------
// Convert a hex-encoded octet (2 characters, i.e. df or 1a).
// ------------------------------------------------------------------------------------
inline
uint8_t HexOctetToDecimal(const char* in) {
inline uint8_t HexOctetToDecimal(const char* in) {
return ((uint8_t)HexDigitToDecimal(in[0])<<4)+(uint8_t)HexDigitToDecimal(in[1]);
}
// ------------------------------------------------------------------------------------
// signed variant of strtoul10
// ------------------------------------------------------------------------------------
inline
int strtol10( const char* in, const char** out=0) {
inline int strtol10( const char* in, const char** out=0) {
bool inv = (*in=='-');
if ( inv || *in == '+' ) {
++in;
@ -163,7 +158,11 @@ int strtol10( const char* in, const char** out=0) {
int value = strtoul10(in,out);
if (inv) {
value = -value;
if (value < INT_MAX) {
value = -value;
} else {
ASSIMP_LOG_WARN( "Converting the string \"", in, "\" into an inverted value resulted in overflow." );
}
}
return value;
}
@ -174,8 +173,7 @@ int strtol10( const char* in, const char** out=0) {
// 0NNN - oct
// NNN - dec
// ------------------------------------------------------------------------------------
inline
unsigned int strtoul_cppstyle( const char* in, const char** out=0) {
inline unsigned int strtoul_cppstyle( const char* in, const char** out=0) {
if ('0' == in[0]) {
return 'x' == in[1] ? strtoul16(in+2,out) : strtoul8(in+1,out);
}
@ -187,8 +185,7 @@ unsigned int strtoul_cppstyle( const char* in, const char** out=0) {
// It is mainly used by fast_atof to prevent ugly and unwanted integer overflows.
// ------------------------------------------------------------------------------------
template<typename ExceptionType = DeadlyImportError>
inline
uint64_t strtoul10_64( const char* in, const char** out=0, unsigned int* max_inout=0) {
inline uint64_t strtoul10_64( const char* in, const char** out=0, unsigned int* max_inout=0) {
unsigned int cur = 0;
uint64_t value = 0;
@ -241,8 +238,7 @@ uint64_t strtoul10_64( const char* in, const char** out=0, unsigned int* max_ino
// signed variant of strtoul10_64
// ------------------------------------------------------------------------------------
template<typename ExceptionType = DeadlyImportError>
inline
int64_t strtol10_64(const char* in, const char** out = 0, unsigned int* max_inout = 0) {
inline int64_t strtol10_64(const char* in, const char** out = 0, unsigned int* max_inout = 0) {
bool inv = (*in == '-');
if ( inv || *in == '+' ) {
++in;
@ -264,8 +260,7 @@ int64_t strtol10_64(const char* in, const char** out = 0, unsigned int* max_inou
// If you find any bugs, please send them to me, niko (at) irrlicht3d.org.
// ------------------------------------------------------------------------------------
template<typename Real, typename ExceptionType = DeadlyImportError>
inline
const char* fast_atoreal_move(const char* c, Real& out, bool check_comma = true) {
inline const char* fast_atoreal_move(const char* c, Real& out, bool check_comma = true) {
Real f = 0;
bool inv = (*c == '-');
@ -354,8 +349,7 @@ const char* fast_atoreal_move(const char* c, Real& out, bool check_comma = true)
// ------------------------------------------------------------------------------------
// The same but more human.
template<typename ExceptionType = DeadlyImportError>
inline
ai_real fast_atof(const char* c) {
inline ai_real fast_atof(const char* c) {
ai_real ret(0.0);
fast_atoreal_move<ai_real, ExceptionType>(c, ret);
@ -372,8 +366,7 @@ ai_real fast_atof( const char* c, const char** cout) {
}
template<typename ExceptionType = DeadlyImportError>
inline
ai_real fast_atof( const char** inout) {
inline ai_real fast_atof( const char** inout) {
ai_real ret(0.0);
*inout = fast_atoreal_move<ai_real, ExceptionType>(*inout, ret);

View File

@ -102,6 +102,10 @@ SET( COMMON
unit/Common/utBaseProcess.cpp
)
SET(Geometry
unit/Geometry/utGeometryUtils.cpp
)
SET( IMPORTERS
unit/ImportExport/Assxml/utAssxmlImportExport.cpp
unit/utLWSImportExport.cpp
@ -200,12 +204,13 @@ SET( POST_PROCESSES
unit/utGenBoundingBoxesProcess.cpp
)
SOURCE_GROUP( UnitTests\\Compiler FILES unit/CCompilerTest.c )
SOURCE_GROUP( UnitTests\\Common FILES ${COMMON} )
SOURCE_GROUP( UnitTests\\ImportExport FILES ${IMPORTERS} )
SOURCE_GROUP( UnitTests\\Material FILES ${MATERIAL} )
SOURCE_GROUP( UnitTests\\Math FILES ${MATH} )
SOURCE_GROUP( UnitTests\\PostProcess FILES ${POST_PROCESSES})
SOURCE_GROUP( UnitTests\\Compiler FILES unit/CCompilerTest.c )
SOURCE_GROUP( UnitTests\\Common FILES ${COMMON} )
SOURCE_GROUP( UnitTests\\GeometryTools FILES ${Geometry} )
SOURCE_GROUP( UnitTests\\ImportExport FILES ${IMPORTERS} )
SOURCE_GROUP( UnitTests\\Material FILES ${MATERIAL} )
SOURCE_GROUP( UnitTests\\Math FILES ${MATH} )
SOURCE_GROUP( UnitTests\\PostProcess FILES ${POST_PROCESSES})
add_executable( unit
unit/CCompilerTest.c
@ -213,6 +218,7 @@ add_executable( unit
../code/Common/Version.cpp
../code/Common/Base64.cpp
${COMMON}
${Geometry}
${IMPORTERS}
${MATERIAL}
${MATH}

Binary file not shown.

After

Width:  |  Height:  |  Size: 192 KiB

View File

@ -1,6 +1,6 @@
class mar expands Actor;
#exec MESH IMPORT MESH=mar ANIVFILE=MODELS\mar_a.3d DATAFILE=MODELS\mar_d.3d X=0 Y=0 Z=0
#exec MESH IMPORT MESH=mar ANIVFILE=MODELS\mar_rifle_a.3d DATAFILE=MODELS\mar_rifle_d.3d X=0 Y=0 Z=0
#exec MESH ORIGIN MESH=mar X=0 Y=0 Z=0
#exec MESH SEQUENCE MESH=mar SEQ=All STARTFRAME=0 NUMFRAMES=30
@ -9,7 +9,7 @@ class mar expands Actor;
#exec MESHMAP NEW MESHMAP=mar MESH=mar
#exec MESHMAP SCALE MESHMAP=mar X=0.1 Y=0.1 Z=0.2
#exec TEXTURE IMPORT NAME=Jtex1 FILE=..\3DS\m_rifl.bmp GROUP=Skins FLAGS=2
#exec TEXTURE IMPORT NAME=Jtex1 FILE=m_rifl.bmp GROUP=Skins FLAGS=2
#exec TEXTURE IMPORT NAME=Jtex1 FILE=texture1.pcx GROUP=Skins PALETTE=Jtex1
#exec MESHMAP SETTEXTURE MESHMAP=mar NUM=1 TEXTURE=Jtex1

Binary file not shown.

View File

@ -32,7 +32,7 @@
*MAP_CLASS "Bitmap"
*MAP_SUBNO 1
*MAP_AMOUNT 1.0000
*BITMAP "../3DS/MP5SIL.BMP"
*BITMAP "mp5sil.bmp"
*MAP_TYPE Screen
*UVW_U_OFFSET 0.000000
*UVW_V_OFFSET 0.000000

View File

@ -32,7 +32,7 @@
*MAP_CLASS "Bitmap"
*MAP_SUBNO 1
*MAP_AMOUNT 1.0000
*BITMAP "../3DS/m_rifl.bmp"
*BITMAP "m_rifl.bmp"
*MAP_TYPE Screen
*UVW_U_OFFSET 0.000000
*UVW_V_OFFSET 0.000000

Binary file not shown.

After

Width:  |  Height:  |  Size: 192 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 192 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 192 KiB

View File

@ -4,4 +4,4 @@ Ka 0.588235 0.588235 0.588235
Ks 0.898039 0.898039 0.898039
Ns 128
Tr 0
map_Kd ./../3DS/m_rifl.bmp
map_Kd m_rifl.bmp

View File

@ -10,7 +10,7 @@ OBJECT poly
name "sphere"
subdiv 3
loc -0.0624103 -0.012381 0.0558408
texture "./../LWO/LWO2/MappingModes/earthSpherical.jpg"
texture "earthSpherical.jpg"
crease 45.000000
numvert 134
-0.00202139 0.0563461 0

View File

@ -10,7 +10,7 @@ OBJECT poly
name "sphere"
subdiv 4
loc -0.0624103 -0.012381 0.0558408
texture "./../LWO/LWO2/MappingModes/earthSpherical.jpg"
texture "earthSpherical.jpg"
texrep 1.9 2.5
texoff 0.019 0.5
crease 45.000000

View File

@ -9,7 +9,7 @@ kids 0
OBJECT poly
name "中国菜"
loc -0.0624103 -0.012381 0.0558408
texture "./../LWO/LWO2/MappingModes/earthSpherical.jpg"
texture "earthSpherical.jpg"
crease 45.000000
numvert 134
-0.00202139 0.0563461 0

Binary file not shown.

After

Width:  |  Height:  |  Size: 412 KiB

View File

@ -329,7 +329,7 @@
<enum name="AutomaticCulling" value="box" />
<int name="DebugDataVisible" value="0" />
<bool name="IsDebugObject" value="false" />
<string name="Mesh" value="../X/dwarf.x" />
<string name="Mesh" value="dwarf.x" />
<bool name="Looping" value="true" />
<bool name="ReadOnlyMaterials" value="false" />
<float name="FramesPerSecond" value="0.250000" />
@ -345,7 +345,7 @@
<float name="Shininess" value="0.000000" />
<float name="Param1" value="0.000000" />
<float name="Param2" value="0.000000" />
<texture name="Texture1" value="../X/axe.jpg" />
<texture name="Texture1" value="axe.jpg" />
<texture name="Texture2" value="" />
<texture name="Texture3" value="" />
<texture name="Texture4" value="" />
@ -384,7 +384,7 @@
<float name="Shininess" value="0.000000" />
<float name="Param1" value="0.000000" />
<float name="Param2" value="0.000000" />
<texture name="Texture1" value="../X/dwarf.jpg" />
<texture name="Texture1" value="dwarf.jpg" />
<texture name="Texture2" value="" />
<texture name="Texture3" value="" />
<texture name="Texture4" value="" />
@ -468,7 +468,7 @@
<enum name="AutomaticCulling" value="box" />
<int name="DebugDataVisible" value="0" />
<bool name="IsDebugObject" value="false" />
<string name="Mesh" value="../X/dwarf.x" />
<string name="Mesh" value="dwarf.x" />
<bool name="Looping" value="true" />
<bool name="ReadOnlyMaterials" value="false" />
<float name="FramesPerSecond" value="0.250000" />
@ -484,7 +484,7 @@
<float name="Shininess" value="0.000000" />
<float name="Param1" value="0.000000" />
<float name="Param2" value="0.000000" />
<texture name="Texture1" value="../X/axe.jpg" />
<texture name="Texture1" value="axe.jpg" />
<texture name="Texture2" value="" />
<texture name="Texture3" value="" />
<texture name="Texture4" value="" />
@ -523,7 +523,7 @@
<float name="Shininess" value="0.000000" />
<float name="Param1" value="0.000000" />
<float name="Param2" value="0.000000" />
<texture name="Texture1" value="../X/dwarf.jpg" />
<texture name="Texture1" value="dwarf.jpg" />
<texture name="Texture2" value="" />
<texture name="Texture3" value="" />
<texture name="Texture4" value="" />
@ -723,7 +723,7 @@
<enum name="AutomaticCulling" value="box" />
<int name="DebugDataVisible" value="0" />
<bool name="IsDebugObject" value="false" />
<string name="Mesh" value="../X/dwarf.x" />
<string name="Mesh" value="dwarf.x" />
<bool name="Looping" value="true" />
<bool name="ReadOnlyMaterials" value="false" />
<float name="FramesPerSecond" value="0.250000" />
@ -739,7 +739,7 @@
<float name="Shininess" value="0.000000" />
<float name="Param1" value="0.000000" />
<float name="Param2" value="0.000000" />
<texture name="Texture1" value="../X/axe.jpg" />
<texture name="Texture1" value="axe.jpg" />
<texture name="Texture2" value="" />
<texture name="Texture3" value="" />
<texture name="Texture4" value="" />
@ -778,7 +778,7 @@
<float name="Shininess" value="0.000000" />
<float name="Param1" value="0.000000" />
<float name="Param2" value="0.000000" />
<texture name="Texture1" value="../X/dwarf.jpg" />
<texture name="Texture1" value="dwarf.jpg" />
<texture name="Texture2" value="" />
<texture name="Texture3" value="" />
<texture name="Texture4" value="" />
@ -920,7 +920,7 @@
<enum name="AutomaticCulling" value="box" />
<int name="DebugDataVisible" value="0" />
<bool name="IsDebugObject" value="false" />
<string name="Mesh" value="../X/dwarf.x" />
<string name="Mesh" value="dwarf.x" />
<bool name="Looping" value="true" />
<bool name="ReadOnlyMaterials" value="false" />
<float name="FramesPerSecond" value="0.250000" />
@ -936,7 +936,7 @@
<float name="Shininess" value="0.000000" />
<float name="Param1" value="0.000000" />
<float name="Param2" value="0.000000" />
<texture name="Texture1" value="../X/axe.jpg" />
<texture name="Texture1" value="axe.jpg" />
<texture name="Texture2" value="" />
<texture name="Texture3" value="" />
<texture name="Texture4" value="" />
@ -975,7 +975,7 @@
<float name="Shininess" value="0.000000" />
<float name="Param1" value="0.000000" />
<float name="Param2" value="0.000000" />
<texture name="Texture1" value="../X/dwarf.jpg" />
<texture name="Texture1" value="dwarf.jpg" />
<texture name="Texture2" value="" />
<texture name="Texture3" value="" />
<texture name="Texture4" value="" />

Some files were not shown because too many files have changed in this diff Show More