Build Assimp from source
This commit is contained in:
		
							
								
								
									
										305
									
								
								thirdparty/assimp/code/FBX/FBXAnimation.cpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										305
									
								
								thirdparty/assimp/code/FBX/FBXAnimation.cpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,305 @@
 | 
			
		||||
/*
 | 
			
		||||
Open Asset Import Library (assimp)
 | 
			
		||||
----------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
Copyright (c) 2006-2019, 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  FBXAnimation.cpp
 | 
			
		||||
 *  @brief Assimp::FBX::AnimationCurve, Assimp::FBX::AnimationCurveNode,
 | 
			
		||||
 *         Assimp::FBX::AnimationLayer, Assimp::FBX::AnimationStack
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef ASSIMP_BUILD_NO_FBX_IMPORTER
 | 
			
		||||
 | 
			
		||||
#include "FBXParser.h"
 | 
			
		||||
#include "FBXDocument.h"
 | 
			
		||||
#include "FBXImporter.h"
 | 
			
		||||
#include "FBXDocumentUtil.h"
 | 
			
		||||
 | 
			
		||||
namespace Assimp {
 | 
			
		||||
namespace FBX {
 | 
			
		||||
 | 
			
		||||
using namespace Util;
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
AnimationCurve::AnimationCurve(uint64_t id, const Element& element, const std::string& name, const Document& /*doc*/)
 | 
			
		||||
: Object(id, element, name)
 | 
			
		||||
{
 | 
			
		||||
    const Scope& sc = GetRequiredScope(element);
 | 
			
		||||
    const Element& KeyTime = GetRequiredElement(sc,"KeyTime");
 | 
			
		||||
    const Element& KeyValueFloat = GetRequiredElement(sc,"KeyValueFloat");
 | 
			
		||||
 | 
			
		||||
    ParseVectorDataArray(keys, KeyTime);
 | 
			
		||||
    ParseVectorDataArray(values, KeyValueFloat);
 | 
			
		||||
 | 
			
		||||
    if(keys.size() != values.size()) {
 | 
			
		||||
        DOMError("the number of key times does not match the number of keyframe values",&KeyTime);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // check if the key times are well-ordered
 | 
			
		||||
    if(!std::equal(keys.begin(), keys.end() - 1, keys.begin() + 1, std::less<KeyTimeList::value_type>())) {
 | 
			
		||||
        DOMError("the keyframes are not in ascending order",&KeyTime);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const Element* KeyAttrDataFloat = sc["KeyAttrDataFloat"];
 | 
			
		||||
    if(KeyAttrDataFloat) {
 | 
			
		||||
        ParseVectorDataArray(attributes, *KeyAttrDataFloat);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const Element* KeyAttrFlags = sc["KeyAttrFlags"];
 | 
			
		||||
    if(KeyAttrFlags) {
 | 
			
		||||
        ParseVectorDataArray(flags, *KeyAttrFlags);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
AnimationCurve::~AnimationCurve()
 | 
			
		||||
{
 | 
			
		||||
    // empty
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
AnimationCurveNode::AnimationCurveNode(uint64_t id, const Element& element, const std::string& name, 
 | 
			
		||||
        const Document& doc, const char* const * target_prop_whitelist /*= NULL*/, 
 | 
			
		||||
        size_t whitelist_size /*= 0*/)
 | 
			
		||||
: Object(id, element, name)
 | 
			
		||||
, target()
 | 
			
		||||
, doc(doc)
 | 
			
		||||
{
 | 
			
		||||
    const Scope& sc = GetRequiredScope(element);
 | 
			
		||||
 | 
			
		||||
    // find target node
 | 
			
		||||
    const char* whitelist[] = {"Model","NodeAttribute","Deformer"};
 | 
			
		||||
    const std::vector<const Connection*>& conns = doc.GetConnectionsBySourceSequenced(ID(),whitelist,3);
 | 
			
		||||
 | 
			
		||||
    for(const Connection* con : conns) {
 | 
			
		||||
 | 
			
		||||
        // link should go for a property
 | 
			
		||||
        if (!con->PropertyName().length()) {
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if(target_prop_whitelist) {
 | 
			
		||||
            const char* const s = con->PropertyName().c_str();
 | 
			
		||||
            bool ok = false;
 | 
			
		||||
            for (size_t i = 0; i < whitelist_size; ++i) {
 | 
			
		||||
                if (!strcmp(s, target_prop_whitelist[i])) {
 | 
			
		||||
                    ok = true;
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (!ok) {
 | 
			
		||||
                throw std::range_error("AnimationCurveNode target property is not in whitelist");
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const Object* const ob = con->DestinationObject();
 | 
			
		||||
        if(!ob) {
 | 
			
		||||
            DOMWarning("failed to read destination object for AnimationCurveNode->Model link, ignoring",&element);
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // XXX support constraints as DOM class
 | 
			
		||||
        //ai_assert(dynamic_cast<const Model*>(ob) || dynamic_cast<const NodeAttribute*>(ob));
 | 
			
		||||
        target = ob;
 | 
			
		||||
        if(!target) {
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        prop = con->PropertyName();
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(!target) {
 | 
			
		||||
        DOMWarning("failed to resolve target Model/NodeAttribute/Constraint for AnimationCurveNode",&element);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    props = GetPropertyTable(doc,"AnimationCurveNode.FbxAnimCurveNode",element,sc,false);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
AnimationCurveNode::~AnimationCurveNode()
 | 
			
		||||
{
 | 
			
		||||
    // empty
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
const AnimationCurveMap& AnimationCurveNode::Curves() const
 | 
			
		||||
{
 | 
			
		||||
    if ( curves.empty() ) {
 | 
			
		||||
        // resolve attached animation curves
 | 
			
		||||
        const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID(),"AnimationCurve");
 | 
			
		||||
 | 
			
		||||
        for(const Connection* con : conns) {
 | 
			
		||||
 | 
			
		||||
            // link should go for a property
 | 
			
		||||
            if (!con->PropertyName().length()) {
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            const Object* const ob = con->SourceObject();
 | 
			
		||||
            if(!ob) {
 | 
			
		||||
                DOMWarning("failed to read source object for AnimationCurve->AnimationCurveNode link, ignoring",&element);
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            const AnimationCurve* const anim = dynamic_cast<const AnimationCurve*>(ob);
 | 
			
		||||
            if(!anim) {
 | 
			
		||||
                DOMWarning("source object for ->AnimationCurveNode link is not an AnimationCurve",&element);
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            curves[con->PropertyName()] = anim;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return curves;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
AnimationLayer::AnimationLayer(uint64_t id, const Element& element, const std::string& name, const Document& doc)
 | 
			
		||||
: Object(id, element, name)
 | 
			
		||||
, doc(doc)
 | 
			
		||||
{
 | 
			
		||||
    const Scope& sc = GetRequiredScope(element);
 | 
			
		||||
 | 
			
		||||
    // note: the props table here bears little importance and is usually absent
 | 
			
		||||
    props = GetPropertyTable(doc,"AnimationLayer.FbxAnimLayer",element,sc, true);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
AnimationLayer::~AnimationLayer()
 | 
			
		||||
{
 | 
			
		||||
    // empty
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
AnimationCurveNodeList AnimationLayer::Nodes(const char* const * target_prop_whitelist /*= NULL*/,
 | 
			
		||||
    size_t whitelist_size /*= 0*/) const
 | 
			
		||||
{
 | 
			
		||||
    AnimationCurveNodeList nodes;
 | 
			
		||||
 | 
			
		||||
    // resolve attached animation nodes
 | 
			
		||||
    const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID(),"AnimationCurveNode");
 | 
			
		||||
    nodes.reserve(conns.size());
 | 
			
		||||
 | 
			
		||||
    for(const Connection* con : conns) {
 | 
			
		||||
 | 
			
		||||
        // link should not go to a property
 | 
			
		||||
        if (con->PropertyName().length()) {
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const Object* const ob = con->SourceObject();
 | 
			
		||||
        if(!ob) {
 | 
			
		||||
            DOMWarning("failed to read source object for AnimationCurveNode->AnimationLayer link, ignoring",&element);
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const AnimationCurveNode* const anim = dynamic_cast<const AnimationCurveNode*>(ob);
 | 
			
		||||
        if(!anim) {
 | 
			
		||||
            DOMWarning("source object for ->AnimationLayer link is not an AnimationCurveNode",&element);
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if(target_prop_whitelist) {
 | 
			
		||||
            const char* s = anim->TargetProperty().c_str();
 | 
			
		||||
            bool ok = false;
 | 
			
		||||
            for (size_t i = 0; i < whitelist_size; ++i) {
 | 
			
		||||
                if (!strcmp(s, target_prop_whitelist[i])) {
 | 
			
		||||
                    ok = true;
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            if(!ok) {
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        nodes.push_back(anim);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return nodes; // pray for NRVO
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
AnimationStack::AnimationStack(uint64_t id, const Element& element, const std::string& name, const Document& doc)
 | 
			
		||||
: Object(id, element, name)
 | 
			
		||||
{
 | 
			
		||||
    const Scope& sc = GetRequiredScope(element);
 | 
			
		||||
 | 
			
		||||
    // note: we don't currently use any of these properties so we shouldn't bother if it is missing
 | 
			
		||||
    props = GetPropertyTable(doc,"AnimationStack.FbxAnimStack",element,sc, true);
 | 
			
		||||
 | 
			
		||||
    // resolve attached animation layers
 | 
			
		||||
    const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID(),"AnimationLayer");
 | 
			
		||||
    layers.reserve(conns.size());
 | 
			
		||||
 | 
			
		||||
    for(const Connection* con : conns) {
 | 
			
		||||
 | 
			
		||||
        // link should not go to a property
 | 
			
		||||
        if (con->PropertyName().length()) {
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const Object* const ob = con->SourceObject();
 | 
			
		||||
        if(!ob) {
 | 
			
		||||
            DOMWarning("failed to read source object for AnimationLayer->AnimationStack link, ignoring",&element);
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const AnimationLayer* const anim = dynamic_cast<const AnimationLayer*>(ob);
 | 
			
		||||
        if(!anim) {
 | 
			
		||||
            DOMWarning("source object for ->AnimationStack link is not an AnimationLayer",&element);
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
        layers.push_back(anim);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
AnimationStack::~AnimationStack()
 | 
			
		||||
{
 | 
			
		||||
    // empty
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} //!FBX
 | 
			
		||||
} //!Assimp
 | 
			
		||||
 | 
			
		||||
#endif // ASSIMP_BUILD_NO_FBX_IMPORTER
 | 
			
		||||
							
								
								
									
										466
									
								
								thirdparty/assimp/code/FBX/FBXBinaryTokenizer.cpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										466
									
								
								thirdparty/assimp/code/FBX/FBXBinaryTokenizer.cpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,466 @@
 | 
			
		||||
/*
 | 
			
		||||
Open Asset Import Library (assimp)
 | 
			
		||||
----------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
Copyright (c) 2006-2019, 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  FBXBinaryTokenizer.cpp
 | 
			
		||||
 *  @brief Implementation of a fake lexer for binary fbx files -
 | 
			
		||||
 *    we emit tokens so the parser needs almost no special handling
 | 
			
		||||
 *    for binary files.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef ASSIMP_BUILD_NO_FBX_IMPORTER
 | 
			
		||||
 | 
			
		||||
#include "FBXTokenizer.h"
 | 
			
		||||
#include "FBXUtil.h"
 | 
			
		||||
#include <assimp/defs.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <assimp/Exceptional.h>
 | 
			
		||||
#include <assimp/ByteSwapper.h>
 | 
			
		||||
 | 
			
		||||
namespace Assimp {
 | 
			
		||||
namespace FBX {
 | 
			
		||||
 | 
			
		||||
//enum Flag
 | 
			
		||||
//{
 | 
			
		||||
//   e_unknown_0 = 1 << 0,
 | 
			
		||||
//   e_unknown_1 = 1 << 1,
 | 
			
		||||
//   e_unknown_2 = 1 << 2,
 | 
			
		||||
//   e_unknown_3 = 1 << 3,
 | 
			
		||||
//   e_unknown_4 = 1 << 4,
 | 
			
		||||
//   e_unknown_5 = 1 << 5,
 | 
			
		||||
//   e_unknown_6 = 1 << 6,
 | 
			
		||||
//   e_unknown_7 = 1 << 7,
 | 
			
		||||
//   e_unknown_8 = 1 << 8,
 | 
			
		||||
//   e_unknown_9 = 1 << 9,
 | 
			
		||||
//   e_unknown_10 = 1 << 10,
 | 
			
		||||
//   e_unknown_11 = 1 << 11,
 | 
			
		||||
//   e_unknown_12 = 1 << 12,
 | 
			
		||||
//   e_unknown_13 = 1 << 13,
 | 
			
		||||
//   e_unknown_14 = 1 << 14,
 | 
			
		||||
//   e_unknown_15 = 1 << 15,
 | 
			
		||||
//   e_unknown_16 = 1 << 16,
 | 
			
		||||
//   e_unknown_17 = 1 << 17,
 | 
			
		||||
//   e_unknown_18 = 1 << 18,
 | 
			
		||||
//   e_unknown_19 = 1 << 19,
 | 
			
		||||
//   e_unknown_20 = 1 << 20,
 | 
			
		||||
//   e_unknown_21 = 1 << 21,
 | 
			
		||||
//   e_unknown_22 = 1 << 22,
 | 
			
		||||
//   e_unknown_23 = 1 << 23,
 | 
			
		||||
//   e_flag_field_size_64_bit = 1 << 24, // Not sure what is
 | 
			
		||||
//   e_unknown_25 = 1 << 25,
 | 
			
		||||
//   e_unknown_26 = 1 << 26,
 | 
			
		||||
//   e_unknown_27 = 1 << 27,
 | 
			
		||||
//   e_unknown_28 = 1 << 28,
 | 
			
		||||
//   e_unknown_29 = 1 << 29,
 | 
			
		||||
//   e_unknown_30 = 1 << 30,
 | 
			
		||||
//   e_unknown_31 = 1 << 31
 | 
			
		||||
//};
 | 
			
		||||
//
 | 
			
		||||
//bool check_flag(uint32_t flags, Flag to_check)
 | 
			
		||||
//{
 | 
			
		||||
//	return (flags & to_check) != 0;
 | 
			
		||||
//}
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
Token::Token(const char* sbegin, const char* send, TokenType type, size_t offset)
 | 
			
		||||
    :
 | 
			
		||||
    #ifdef DEBUG
 | 
			
		||||
    contents(sbegin, static_cast<size_t>(send-sbegin)),
 | 
			
		||||
    #endif
 | 
			
		||||
    sbegin(sbegin)
 | 
			
		||||
    , send(send)
 | 
			
		||||
    , type(type)
 | 
			
		||||
    , line(offset)
 | 
			
		||||
    , column(BINARY_MARKER)
 | 
			
		||||
{
 | 
			
		||||
    ai_assert(sbegin);
 | 
			
		||||
    ai_assert(send);
 | 
			
		||||
 | 
			
		||||
    // binary tokens may have zero length because they are sometimes dummies
 | 
			
		||||
    // inserted by TokenizeBinary()
 | 
			
		||||
    ai_assert(send >= sbegin);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
namespace {
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
// signal tokenization error, this is always unrecoverable. Throws DeadlyImportError.
 | 
			
		||||
AI_WONT_RETURN void TokenizeError(const std::string& message, size_t offset) AI_WONT_RETURN_SUFFIX;
 | 
			
		||||
AI_WONT_RETURN void TokenizeError(const std::string& message, size_t offset)
 | 
			
		||||
{
 | 
			
		||||
    throw DeadlyImportError(Util::AddOffset("FBX-Tokenize",message,offset));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
size_t Offset(const char* begin, const char* cursor) {
 | 
			
		||||
    ai_assert(begin <= cursor);
 | 
			
		||||
 | 
			
		||||
    return cursor - begin;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
void TokenizeError(const std::string& message, const char* begin, const char* cursor) {
 | 
			
		||||
    TokenizeError(message, Offset(begin, cursor));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
uint32_t ReadWord(const char* input, const char*& cursor, const char* end) {
 | 
			
		||||
    const size_t k_to_read = sizeof( uint32_t );
 | 
			
		||||
    if(Offset(cursor, end) < k_to_read ) {
 | 
			
		||||
        TokenizeError("cannot ReadWord, out of bounds",input, cursor);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    uint32_t word;
 | 
			
		||||
    ::memcpy(&word, cursor, 4);
 | 
			
		||||
    AI_SWAP4(word);
 | 
			
		||||
 | 
			
		||||
    cursor += k_to_read;
 | 
			
		||||
 | 
			
		||||
    return word;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
uint64_t ReadDoubleWord(const char* input, const char*& cursor, const char* end) {
 | 
			
		||||
    const size_t k_to_read = sizeof(uint64_t);
 | 
			
		||||
    if(Offset(cursor, end) < k_to_read) {
 | 
			
		||||
        TokenizeError("cannot ReadDoubleWord, out of bounds",input, cursor);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    uint64_t dword /*= *reinterpret_cast<const uint64_t*>(cursor)*/;
 | 
			
		||||
    ::memcpy( &dword, cursor, sizeof( uint64_t ) );
 | 
			
		||||
    AI_SWAP8(dword);
 | 
			
		||||
 | 
			
		||||
    cursor += k_to_read;
 | 
			
		||||
 | 
			
		||||
    return dword;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
uint8_t ReadByte(const char* input, const char*& cursor, const char* end) {
 | 
			
		||||
    if(Offset(cursor, end) < sizeof( uint8_t ) ) {
 | 
			
		||||
        TokenizeError("cannot ReadByte, out of bounds",input, cursor);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    uint8_t word;/* = *reinterpret_cast< const uint8_t* >( cursor )*/
 | 
			
		||||
    ::memcpy( &word, cursor, sizeof( uint8_t ) );
 | 
			
		||||
    ++cursor;
 | 
			
		||||
 | 
			
		||||
    return word;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
unsigned int ReadString(const char*& sbegin_out, const char*& send_out, const char* input,
 | 
			
		||||
        const char*& cursor, const char* end, bool long_length = false, bool allow_null = false) {
 | 
			
		||||
    const uint32_t len_len = long_length ? 4 : 1;
 | 
			
		||||
    if(Offset(cursor, end) < len_len) {
 | 
			
		||||
        TokenizeError("cannot ReadString, out of bounds reading length",input, cursor);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const uint32_t length = long_length ? ReadWord(input, cursor, end) : ReadByte(input, cursor, end);
 | 
			
		||||
 | 
			
		||||
    if (Offset(cursor, end) < length) {
 | 
			
		||||
        TokenizeError("cannot ReadString, length is out of bounds",input, cursor);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    sbegin_out = cursor;
 | 
			
		||||
    cursor += length;
 | 
			
		||||
 | 
			
		||||
    send_out = cursor;
 | 
			
		||||
 | 
			
		||||
    if(!allow_null) {
 | 
			
		||||
        for (unsigned int i = 0; i < length; ++i) {
 | 
			
		||||
            if(sbegin_out[i] == '\0') {
 | 
			
		||||
                TokenizeError("failed ReadString, unexpected NUL character in string",input, cursor);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return length;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
void ReadData(const char*& sbegin_out, const char*& send_out, const char* input, const char*& cursor, const char* end) {
 | 
			
		||||
    if(Offset(cursor, end) < 1) {
 | 
			
		||||
        TokenizeError("cannot ReadData, out of bounds reading length",input, cursor);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const char type = *cursor;
 | 
			
		||||
    sbegin_out = cursor++;
 | 
			
		||||
 | 
			
		||||
    switch(type)
 | 
			
		||||
    {
 | 
			
		||||
        // 16 bit int
 | 
			
		||||
    case 'Y':
 | 
			
		||||
        cursor += 2;
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
        // 1 bit bool flag (yes/no)
 | 
			
		||||
    case 'C':
 | 
			
		||||
        cursor += 1;
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
        // 32 bit int
 | 
			
		||||
    case 'I':
 | 
			
		||||
        // <- fall through
 | 
			
		||||
 | 
			
		||||
        // float
 | 
			
		||||
    case 'F':
 | 
			
		||||
        cursor += 4;
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
        // double
 | 
			
		||||
    case 'D':
 | 
			
		||||
        cursor += 8;
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
        // 64 bit int
 | 
			
		||||
    case 'L':
 | 
			
		||||
        cursor += 8;
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
        // note: do not write cursor += ReadWord(...cursor) as this would be UB
 | 
			
		||||
 | 
			
		||||
        // raw binary data
 | 
			
		||||
    case 'R':
 | 
			
		||||
    {
 | 
			
		||||
        const uint32_t length = ReadWord(input, cursor, end);
 | 
			
		||||
        cursor += length;
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    case 'b':
 | 
			
		||||
        // TODO: what is the 'b' type code? Right now we just skip over it /
 | 
			
		||||
        // take the full range we could get
 | 
			
		||||
        cursor = end;
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
        // array of *
 | 
			
		||||
    case 'f':
 | 
			
		||||
    case 'd':
 | 
			
		||||
    case 'l':
 | 
			
		||||
    case 'i':
 | 
			
		||||
    case 'c':   {
 | 
			
		||||
        const uint32_t length = ReadWord(input, cursor, end);
 | 
			
		||||
        const uint32_t encoding = ReadWord(input, cursor, end);
 | 
			
		||||
 | 
			
		||||
        const uint32_t comp_len = ReadWord(input, cursor, end);
 | 
			
		||||
 | 
			
		||||
        // compute length based on type and check against the stored value
 | 
			
		||||
        if(encoding == 0) {
 | 
			
		||||
            uint32_t stride = 0;
 | 
			
		||||
            switch(type)
 | 
			
		||||
            {
 | 
			
		||||
            case 'f':
 | 
			
		||||
            case 'i':
 | 
			
		||||
                stride = 4;
 | 
			
		||||
                break;
 | 
			
		||||
 | 
			
		||||
            case 'd':
 | 
			
		||||
            case 'l':
 | 
			
		||||
                stride = 8;
 | 
			
		||||
                break;
 | 
			
		||||
 | 
			
		||||
            case 'c':
 | 
			
		||||
                stride = 1;
 | 
			
		||||
                break;
 | 
			
		||||
 | 
			
		||||
            default:
 | 
			
		||||
                ai_assert(false);
 | 
			
		||||
            };
 | 
			
		||||
            ai_assert(stride > 0);
 | 
			
		||||
            if(length * stride != comp_len) {
 | 
			
		||||
                TokenizeError("cannot ReadData, calculated data stride differs from what the file claims",input, cursor);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        // zip/deflate algorithm (encoding==1)? take given length. anything else? die
 | 
			
		||||
        else if (encoding != 1) {
 | 
			
		||||
            TokenizeError("cannot ReadData, unknown encoding",input, cursor);
 | 
			
		||||
        }
 | 
			
		||||
        cursor += comp_len;
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
        // string
 | 
			
		||||
    case 'S': {
 | 
			
		||||
        const char* sb, *se;
 | 
			
		||||
        // 0 characters can legally happen in such strings
 | 
			
		||||
        ReadString(sb, se, input, cursor, end, true, true);
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
    default:
 | 
			
		||||
        TokenizeError("cannot ReadData, unexpected type code: " + std::string(&type, 1),input, cursor);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(cursor > end) {
 | 
			
		||||
        TokenizeError("cannot ReadData, the remaining size is too small for the data type: " + std::string(&type, 1),input, cursor);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // the type code is contained in the returned range
 | 
			
		||||
    send_out = cursor;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
bool ReadScope(TokenList& output_tokens, 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);
 | 
			
		||||
 | 
			
		||||
    // we may get 0 if reading reached the end of the file -
 | 
			
		||||
    // fbx files have a mysterious extra footer which I don't know
 | 
			
		||||
    // how to extract any information from, but at least it always
 | 
			
		||||
    // starts with a 0.
 | 
			
		||||
    if(!end_offset) {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(end_offset > Offset(input, end)) {
 | 
			
		||||
        TokenizeError("block offset is out of range",input, cursor);
 | 
			
		||||
    }
 | 
			
		||||
    else if(end_offset < Offset(input, cursor)) {
 | 
			
		||||
        TokenizeError("block offset is negative out of range",input, cursor);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // the second data word contains the number of properties in the scope
 | 
			
		||||
	const uint64_t prop_count = is64bits ? ReadDoubleWord(input, cursor, end) : ReadWord(input, cursor, end);
 | 
			
		||||
 | 
			
		||||
    // the third data word contains the length of the property list
 | 
			
		||||
	const uint64_t prop_length = is64bits ? ReadDoubleWord(input, cursor, end) : ReadWord(input, cursor, end);
 | 
			
		||||
 | 
			
		||||
    // now comes the name of the scope/key
 | 
			
		||||
    const char* sbeg, *send;
 | 
			
		||||
    ReadString(sbeg, send, input, cursor, end);
 | 
			
		||||
 | 
			
		||||
    output_tokens.push_back(new_Token(sbeg, send, TokenType_KEY, Offset(input, cursor) ));
 | 
			
		||||
 | 
			
		||||
    // now come the individual properties
 | 
			
		||||
    const char* begin_cursor = cursor;
 | 
			
		||||
    for (unsigned int i = 0; i < prop_count; ++i) {
 | 
			
		||||
        ReadData(sbeg, send, input, cursor, begin_cursor + prop_length);
 | 
			
		||||
 | 
			
		||||
        output_tokens.push_back(new_Token(sbeg, send, TokenType_DATA, Offset(input, cursor) ));
 | 
			
		||||
 | 
			
		||||
        if(i != prop_count-1) {
 | 
			
		||||
            output_tokens.push_back(new_Token(cursor, cursor + 1, TokenType_COMMA, Offset(input, cursor) ));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (Offset(begin_cursor, cursor) != prop_length) {
 | 
			
		||||
        TokenizeError("property length not reached, something is wrong",input, cursor);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // at the end of each nested block, there is a NUL record to indicate
 | 
			
		||||
    // that the sub-scope exists (i.e. to distinguish between P: and P : {})
 | 
			
		||||
    // this NUL record is 13 bytes long on 32 bit version and 25 bytes long on 64 bit.
 | 
			
		||||
	const size_t sentinel_block_length = is64bits ? (sizeof(uint64_t)* 3 + 1) : (sizeof(uint32_t)* 3 + 1);
 | 
			
		||||
 | 
			
		||||
    if (Offset(input, cursor) < end_offset) {
 | 
			
		||||
        if (end_offset - Offset(input, cursor) < sentinel_block_length) {
 | 
			
		||||
            TokenizeError("insufficient padding bytes at block end",input, cursor);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        output_tokens.push_back(new_Token(cursor, cursor + 1, TokenType_OPEN_BRACKET, Offset(input, 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);
 | 
			
		||||
        }
 | 
			
		||||
        output_tokens.push_back(new_Token(cursor, cursor + 1, TokenType_CLOSE_BRACKET, Offset(input, cursor) ));
 | 
			
		||||
 | 
			
		||||
        for (unsigned int i = 0; i < sentinel_block_length; ++i) {
 | 
			
		||||
            if(cursor[i] != '\0') {
 | 
			
		||||
                TokenizeError("failed to read nested block sentinel, expected all bytes to be 0",input, cursor);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        cursor += sentinel_block_length;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (Offset(input, cursor) != end_offset) {
 | 
			
		||||
        TokenizeError("scope length not reached, something is wrong",input, cursor);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // anonymous namespace
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
// 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)
 | 
			
		||||
{
 | 
			
		||||
    ai_assert(input);
 | 
			
		||||
 | 
			
		||||
    if(length < 0x1b) {
 | 
			
		||||
        TokenizeError("file is too short",0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //uint32_t offset = 0x15;
 | 
			
		||||
/*    const char* cursor = input + 0x15;
 | 
			
		||||
 | 
			
		||||
    const uint32_t flags = ReadWord(input, cursor, input + length);
 | 
			
		||||
 | 
			
		||||
    const uint8_t padding_0 = ReadByte(input, cursor, input + length); // unused
 | 
			
		||||
    const uint8_t padding_1 = ReadByte(input, cursor, input + length); // unused*/
 | 
			
		||||
 | 
			
		||||
    if (strncmp(input,"Kaydara FBX Binary",18)) {
 | 
			
		||||
        TokenizeError("magic bytes not found",0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const char* cursor = input + 18;
 | 
			
		||||
	/*Result ignored*/ ReadByte(input, cursor, input + length);
 | 
			
		||||
	/*Result ignored*/ ReadByte(input, cursor, input + length);
 | 
			
		||||
	/*Result ignored*/ ReadByte(input, cursor, input + length);
 | 
			
		||||
	/*Result ignored*/ ReadByte(input, cursor, input + length);
 | 
			
		||||
	/*Result ignored*/ ReadByte(input, cursor, input + length);
 | 
			
		||||
	const uint32_t version = ReadWord(input, cursor, input + length);
 | 
			
		||||
	const bool is64bits = version >= 7500;
 | 
			
		||||
    const char *end = input + length;
 | 
			
		||||
    while (cursor < end ) {
 | 
			
		||||
		if (!ReadScope(output_tokens, input, cursor, input + length, is64bits)) {
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // !FBX
 | 
			
		||||
} // !Assimp
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										86
									
								
								thirdparty/assimp/code/FBX/FBXCommon.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								thirdparty/assimp/code/FBX/FBXCommon.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,86 @@
 | 
			
		||||
/*
 | 
			
		||||
Open Asset Import Library (assimp)
 | 
			
		||||
----------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
Copyright (c) 2006-2019, 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 FBXCommon.h
 | 
			
		||||
* Some useful constants and enums for dealing with FBX files.
 | 
			
		||||
*/
 | 
			
		||||
#ifndef AI_FBXCOMMON_H_INC
 | 
			
		||||
#define AI_FBXCOMMON_H_INC
 | 
			
		||||
 | 
			
		||||
#ifndef ASSIMP_BUILD_NO_FBX_EXPORTER
 | 
			
		||||
 | 
			
		||||
namespace Assimp {
 | 
			
		||||
namespace FBX
 | 
			
		||||
{
 | 
			
		||||
    const std::string NULL_RECORD = { // 13 null bytes
 | 
			
		||||
        '\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0'
 | 
			
		||||
    }; // who knows why
 | 
			
		||||
    const std::string SEPARATOR = {'\x00', '\x01'}; // for use inside strings
 | 
			
		||||
    const std::string MAGIC_NODE_TAG = "_$AssimpFbx$"; // from import
 | 
			
		||||
    const int64_t SECOND = 46186158000; // FBX's kTime unit
 | 
			
		||||
 | 
			
		||||
    // rotation order. We'll probably use EulerXYZ for everything
 | 
			
		||||
    enum RotOrder {
 | 
			
		||||
        RotOrder_EulerXYZ = 0,
 | 
			
		||||
        RotOrder_EulerXZY,
 | 
			
		||||
        RotOrder_EulerYZX,
 | 
			
		||||
        RotOrder_EulerYXZ,
 | 
			
		||||
        RotOrder_EulerZXY,
 | 
			
		||||
        RotOrder_EulerZYX,
 | 
			
		||||
 | 
			
		||||
        RotOrder_SphericXYZ,
 | 
			
		||||
 | 
			
		||||
        RotOrder_MAX // end-of-enum sentinel
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    // transformation inheritance method. Most of the time RSrs
 | 
			
		||||
    enum TransformInheritance {
 | 
			
		||||
        TransformInheritance_RrSs = 0,
 | 
			
		||||
        TransformInheritance_RSrs,
 | 
			
		||||
        TransformInheritance_Rrs,
 | 
			
		||||
 | 
			
		||||
        TransformInheritance_MAX // end-of-enum sentinel
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
#endif // ASSIMP_BUILD_NO_FBX_EXPORTER
 | 
			
		||||
 | 
			
		||||
#endif // AI_FBXCOMMON_H_INC
 | 
			
		||||
							
								
								
									
										70
									
								
								thirdparty/assimp/code/FBX/FBXCompileConfig.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								thirdparty/assimp/code/FBX/FBXCompileConfig.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,70 @@
 | 
			
		||||
/*
 | 
			
		||||
Open Asset Import Library (assimp)
 | 
			
		||||
----------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
Copyright (c) 2006-2019, 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  FBXCompileConfig.h
 | 
			
		||||
 *  @brief FBX importer compile-time switches
 | 
			
		||||
 */
 | 
			
		||||
#ifndef INCLUDED_AI_FBX_COMPILECONFIG_H
 | 
			
		||||
#define INCLUDED_AI_FBX_COMPILECONFIG_H
 | 
			
		||||
 | 
			
		||||
#include <map>
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
#if _MSC_VER > 1500 || (defined __GNUC___)
 | 
			
		||||
#   define ASSIMP_FBX_USE_UNORDERED_MULTIMAP
 | 
			
		||||
#   else
 | 
			
		||||
#   define fbx_unordered_map map
 | 
			
		||||
#   define fbx_unordered_multimap multimap
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef ASSIMP_FBX_USE_UNORDERED_MULTIMAP
 | 
			
		||||
#   include <unordered_map>
 | 
			
		||||
#   if _MSC_VER > 1600
 | 
			
		||||
#       define fbx_unordered_map unordered_map
 | 
			
		||||
#       define fbx_unordered_multimap unordered_multimap
 | 
			
		||||
#   else
 | 
			
		||||
#       define fbx_unordered_map tr1::unordered_map
 | 
			
		||||
#       define fbx_unordered_multimap tr1::unordered_multimap
 | 
			
		||||
#   endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif // INCLUDED_AI_FBX_COMPILECONFIG_H
 | 
			
		||||
							
								
								
									
										3615
									
								
								thirdparty/assimp/code/FBX/FBXConverter.cpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										3615
									
								
								thirdparty/assimp/code/FBX/FBXConverter.cpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										464
									
								
								thirdparty/assimp/code/FBX/FBXConverter.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										464
									
								
								thirdparty/assimp/code/FBX/FBXConverter.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,464 @@
 | 
			
		||||
/*
 | 
			
		||||
Open Asset Import Library (assimp)
 | 
			
		||||
----------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
Copyright (c) 2006-2019, 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  FBXDConverter.h
 | 
			
		||||
 *  @brief FBX DOM to aiScene conversion
 | 
			
		||||
 */
 | 
			
		||||
#ifndef INCLUDED_AI_FBX_CONVERTER_H
 | 
			
		||||
#define INCLUDED_AI_FBX_CONVERTER_H
 | 
			
		||||
 | 
			
		||||
#include "FBXParser.h"
 | 
			
		||||
#include "FBXMeshGeometry.h"
 | 
			
		||||
#include "FBXDocument.h"
 | 
			
		||||
#include "FBXUtil.h"
 | 
			
		||||
#include "FBXProperties.h"
 | 
			
		||||
#include "FBXImporter.h"
 | 
			
		||||
 | 
			
		||||
#include <assimp/anim.h>
 | 
			
		||||
#include <assimp/material.h>
 | 
			
		||||
#include <assimp/light.h>
 | 
			
		||||
#include <assimp/texture.h>
 | 
			
		||||
#include <assimp/camera.h>
 | 
			
		||||
#include <assimp/StringComparison.h>
 | 
			
		||||
#include <unordered_map>
 | 
			
		||||
#include <unordered_set>
 | 
			
		||||
 | 
			
		||||
struct aiScene;
 | 
			
		||||
struct aiNode;
 | 
			
		||||
struct aiMaterial;
 | 
			
		||||
 | 
			
		||||
struct morphKeyData {
 | 
			
		||||
    std::vector<unsigned int> values;
 | 
			
		||||
    std::vector<float> weights;
 | 
			
		||||
};
 | 
			
		||||
typedef std::map<int64_t, morphKeyData*> morphAnimData;
 | 
			
		||||
 | 
			
		||||
namespace Assimp {
 | 
			
		||||
namespace FBX {
 | 
			
		||||
 | 
			
		||||
class Document;
 | 
			
		||||
/** 
 | 
			
		||||
 *  Convert a FBX #Document to #aiScene
 | 
			
		||||
 *  @param out Empty scene to be populated
 | 
			
		||||
 *  @param doc Parsed FBX document
 | 
			
		||||
 *  @param removeEmptyBones Will remove bones, which do not have any references to vertices.
 | 
			
		||||
 */
 | 
			
		||||
void ConvertToAssimpScene(aiScene* out, const Document& doc, bool removeEmptyBones);
 | 
			
		||||
 | 
			
		||||
/** Dummy class to encapsulate the conversion process */
 | 
			
		||||
class FBXConverter {
 | 
			
		||||
public:
 | 
			
		||||
    /**
 | 
			
		||||
    *  The different parts that make up the final local transformation of a fbx-node
 | 
			
		||||
    */
 | 
			
		||||
    enum TransformationComp {
 | 
			
		||||
        TransformationComp_GeometricScalingInverse = 0,
 | 
			
		||||
        TransformationComp_GeometricRotationInverse,
 | 
			
		||||
        TransformationComp_GeometricTranslationInverse,
 | 
			
		||||
        TransformationComp_Translation,
 | 
			
		||||
        TransformationComp_RotationOffset,
 | 
			
		||||
        TransformationComp_RotationPivot,
 | 
			
		||||
        TransformationComp_PreRotation,
 | 
			
		||||
        TransformationComp_Rotation,
 | 
			
		||||
        TransformationComp_PostRotation,
 | 
			
		||||
        TransformationComp_RotationPivotInverse,
 | 
			
		||||
        TransformationComp_ScalingOffset,
 | 
			
		||||
        TransformationComp_ScalingPivot,
 | 
			
		||||
        TransformationComp_Scaling,
 | 
			
		||||
        TransformationComp_ScalingPivotInverse,
 | 
			
		||||
        TransformationComp_GeometricTranslation,
 | 
			
		||||
        TransformationComp_GeometricRotation,
 | 
			
		||||
        TransformationComp_GeometricScaling,
 | 
			
		||||
 | 
			
		||||
        TransformationComp_MAXIMUM
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
    FBXConverter(aiScene* out, const Document& doc, bool removeEmptyBones);
 | 
			
		||||
    ~FBXConverter();
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    // ------------------------------------------------------------------------------------------------
 | 
			
		||||
    // find scene root and trigger recursive scene conversion
 | 
			
		||||
    void ConvertRootNode();
 | 
			
		||||
 | 
			
		||||
    // ------------------------------------------------------------------------------------------------
 | 
			
		||||
    // collect and assign child nodes
 | 
			
		||||
    void ConvertNodes(uint64_t id, aiNode& parent, const aiMatrix4x4& parent_transform = aiMatrix4x4());
 | 
			
		||||
 | 
			
		||||
    // ------------------------------------------------------------------------------------------------
 | 
			
		||||
    void ConvertLights(const Model& model, const std::string &orig_name );
 | 
			
		||||
 | 
			
		||||
    // ------------------------------------------------------------------------------------------------
 | 
			
		||||
    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 );
 | 
			
		||||
 | 
			
		||||
    // ------------------------------------------------------------------------------------------------
 | 
			
		||||
    void GetUniqueName( const std::string &name, std::string& uniqueName );
 | 
			
		||||
 | 
			
		||||
    // ------------------------------------------------------------------------------------------------
 | 
			
		||||
    // this returns unified names usable within assimp identifiers (i.e. no space characters -
 | 
			
		||||
    // while these would be allowed, they are a potential trouble spot so better not use them).
 | 
			
		||||
    const char* NameTransformationComp(TransformationComp comp);
 | 
			
		||||
 | 
			
		||||
    // ------------------------------------------------------------------------------------------------
 | 
			
		||||
    // Returns an unique name for a node or traverses up a hierarchy until a non-empty name is found and
 | 
			
		||||
    // then makes this name unique
 | 
			
		||||
    std::string MakeUniqueNodeName(const Model* const model, const aiNode& parent);
 | 
			
		||||
 | 
			
		||||
    // ------------------------------------------------------------------------------------------------
 | 
			
		||||
    // note: this returns the REAL fbx property names
 | 
			
		||||
    const char* NameTransformationCompProperty(TransformationComp comp);
 | 
			
		||||
 | 
			
		||||
    // ------------------------------------------------------------------------------------------------
 | 
			
		||||
    aiVector3D TransformationCompDefaultValue(TransformationComp comp);
 | 
			
		||||
 | 
			
		||||
    // ------------------------------------------------------------------------------------------------
 | 
			
		||||
    void GetRotationMatrix(Model::RotOrder mode, const aiVector3D& rotation, aiMatrix4x4& out);
 | 
			
		||||
    // ------------------------------------------------------------------------------------------------
 | 
			
		||||
    /**
 | 
			
		||||
    *  checks if a node has more than just scaling, rotation and translation components
 | 
			
		||||
    */
 | 
			
		||||
    bool NeedsComplexTransformationChain(const Model& model);
 | 
			
		||||
 | 
			
		||||
    // ------------------------------------------------------------------------------------------------
 | 
			
		||||
    // note: name must be a FixNodeName() result
 | 
			
		||||
    std::string NameTransformationChainNode(const std::string& name, TransformationComp comp);
 | 
			
		||||
 | 
			
		||||
    // ------------------------------------------------------------------------------------------------
 | 
			
		||||
    /**
 | 
			
		||||
    *  note: memory for output_nodes will be managed by the caller
 | 
			
		||||
    */
 | 
			
		||||
    bool GenerateTransformationNodeChain(const Model& model, const std::string& name, std::vector<aiNode*>& output_nodes, std::vector<aiNode*>& post_output_nodes);
 | 
			
		||||
 | 
			
		||||
    // ------------------------------------------------------------------------------------------------
 | 
			
		||||
    void SetupNodeMetadata(const Model& model, aiNode& nd);
 | 
			
		||||
 | 
			
		||||
    // ------------------------------------------------------------------------------------------------
 | 
			
		||||
    void ConvertModel(const Model& model, aiNode& nd, const aiMatrix4x4& node_global_transform);
 | 
			
		||||
    
 | 
			
		||||
    // ------------------------------------------------------------------------------------------------
 | 
			
		||||
    // MeshGeometry -> aiMesh, return mesh index + 1 or 0 if the conversion failed
 | 
			
		||||
    std::vector<unsigned int> ConvertMesh(const MeshGeometry& mesh, const Model& model,
 | 
			
		||||
        const aiMatrix4x4& node_global_transform, aiNode& nd);
 | 
			
		||||
 | 
			
		||||
    // ------------------------------------------------------------------------------------------------
 | 
			
		||||
    std::vector<unsigned int> ConvertLine(const LineGeometry& line, const Model& model,
 | 
			
		||||
        const aiMatrix4x4& node_global_transform, aiNode& nd);
 | 
			
		||||
 | 
			
		||||
    // ------------------------------------------------------------------------------------------------
 | 
			
		||||
    aiMesh* SetupEmptyMesh(const Geometry& mesh, aiNode& nd);
 | 
			
		||||
 | 
			
		||||
    // ------------------------------------------------------------------------------------------------
 | 
			
		||||
    unsigned int ConvertMeshSingleMaterial(const MeshGeometry& mesh, const Model& model,
 | 
			
		||||
        const aiMatrix4x4& node_global_transform, aiNode& nd);
 | 
			
		||||
 | 
			
		||||
    // ------------------------------------------------------------------------------------------------
 | 
			
		||||
    std::vector<unsigned int> ConvertMeshMultiMaterial(const MeshGeometry& mesh, const Model& model,
 | 
			
		||||
        const aiMatrix4x4& node_global_transform, aiNode& nd);
 | 
			
		||||
 | 
			
		||||
    // ------------------------------------------------------------------------------------------------
 | 
			
		||||
    unsigned int ConvertMeshMultiMaterial(const MeshGeometry& mesh, const Model& model,
 | 
			
		||||
        MatIndexArray::value_type index,
 | 
			
		||||
        const aiMatrix4x4& node_global_transform, aiNode& nd);
 | 
			
		||||
 | 
			
		||||
    // ------------------------------------------------------------------------------------------------
 | 
			
		||||
    static const unsigned int NO_MATERIAL_SEPARATION = /* std::numeric_limits<unsigned int>::max() */
 | 
			
		||||
        static_cast<unsigned int>(-1);
 | 
			
		||||
 | 
			
		||||
    // ------------------------------------------------------------------------------------------------
 | 
			
		||||
    /**
 | 
			
		||||
    *  - if materialIndex == NO_MATERIAL_SEPARATION, materials are not taken into
 | 
			
		||||
    *    account when determining which weights to include.
 | 
			
		||||
    *  - outputVertStartIndices is only used when a material index is specified, it gives for
 | 
			
		||||
    *    each output vertex the DOM index it maps to.
 | 
			
		||||
    */
 | 
			
		||||
    void ConvertWeights(aiMesh* out, const Model& model, const MeshGeometry& geo,
 | 
			
		||||
        const aiMatrix4x4& node_global_transform = aiMatrix4x4(),
 | 
			
		||||
        unsigned int materialIndex = NO_MATERIAL_SEPARATION,
 | 
			
		||||
        std::vector<unsigned int>* outputVertStartIndices = NULL);
 | 
			
		||||
 | 
			
		||||
    // ------------------------------------------------------------------------------------------------
 | 
			
		||||
    void ConvertCluster(std::vector<aiBone*>& bones, const Model& /*model*/, const Cluster& cl,
 | 
			
		||||
        std::vector<size_t>& out_indices,
 | 
			
		||||
        std::vector<size_t>& index_out_indices,
 | 
			
		||||
        std::vector<size_t>& count_out_indices,
 | 
			
		||||
        const aiMatrix4x4& node_global_transform);
 | 
			
		||||
 | 
			
		||||
    // ------------------------------------------------------------------------------------------------
 | 
			
		||||
    void ConvertMaterialForMesh(aiMesh* out, const Model& model, const MeshGeometry& geo,
 | 
			
		||||
        MatIndexArray::value_type materialIndex);
 | 
			
		||||
 | 
			
		||||
    // ------------------------------------------------------------------------------------------------
 | 
			
		||||
    unsigned int GetDefaultMaterial();
 | 
			
		||||
 | 
			
		||||
    // ------------------------------------------------------------------------------------------------
 | 
			
		||||
    // Material -> aiMaterial
 | 
			
		||||
    unsigned int ConvertMaterial(const Material& material, const MeshGeometry* const mesh);
 | 
			
		||||
 | 
			
		||||
    // ------------------------------------------------------------------------------------------------
 | 
			
		||||
    // Video -> aiTexture
 | 
			
		||||
    unsigned int ConvertVideo(const Video& video);
 | 
			
		||||
 | 
			
		||||
    // ------------------------------------------------------------------------------------------------
 | 
			
		||||
    // convert embedded texture if necessary and return actual texture path
 | 
			
		||||
    aiString GetTexturePath(const Texture* tex);
 | 
			
		||||
 | 
			
		||||
    // ------------------------------------------------------------------------------------------------
 | 
			
		||||
    void TrySetTextureProperties(aiMaterial* out_mat, const TextureMap& textures,
 | 
			
		||||
        const std::string& propName,
 | 
			
		||||
        aiTextureType target, const MeshGeometry* const mesh);
 | 
			
		||||
 | 
			
		||||
    // ------------------------------------------------------------------------------------------------
 | 
			
		||||
    void TrySetTextureProperties(aiMaterial* out_mat, const LayeredTextureMap& layeredTextures,
 | 
			
		||||
        const std::string& propName,
 | 
			
		||||
        aiTextureType target, const MeshGeometry* const mesh);
 | 
			
		||||
 | 
			
		||||
    // ------------------------------------------------------------------------------------------------
 | 
			
		||||
    void SetTextureProperties(aiMaterial* out_mat, const TextureMap& textures, const MeshGeometry* const mesh);
 | 
			
		||||
 | 
			
		||||
    // ------------------------------------------------------------------------------------------------
 | 
			
		||||
    void SetTextureProperties(aiMaterial* out_mat, const LayeredTextureMap& layeredTextures, const MeshGeometry* const mesh);
 | 
			
		||||
 | 
			
		||||
    // ------------------------------------------------------------------------------------------------
 | 
			
		||||
    aiColor3D GetColorPropertyFromMaterial(const PropertyTable& props, const std::string& baseName,
 | 
			
		||||
        bool& result);
 | 
			
		||||
    aiColor3D GetColorPropertyFactored(const PropertyTable& props, const std::string& colorName,
 | 
			
		||||
        const std::string& factorName, bool& result, bool useTemplate = true);
 | 
			
		||||
    aiColor3D GetColorProperty(const PropertyTable& props, const std::string& colorName,
 | 
			
		||||
        bool& result, bool useTemplate = true);
 | 
			
		||||
 | 
			
		||||
    // ------------------------------------------------------------------------------------------------
 | 
			
		||||
    void SetShadingPropertiesCommon(aiMaterial* out_mat, const PropertyTable& props);
 | 
			
		||||
    void SetShadingPropertiesRaw(aiMaterial* out_mat, const PropertyTable& props, const TextureMap& textures, const MeshGeometry* const mesh);
 | 
			
		||||
 | 
			
		||||
    // ------------------------------------------------------------------------------------------------
 | 
			
		||||
    // get the number of fps for a FrameRate enumerated value
 | 
			
		||||
    static double FrameRateToDouble(FileGlobalSettings::FrameRate fp, double customFPSVal = -1.0);
 | 
			
		||||
 | 
			
		||||
    // ------------------------------------------------------------------------------------------------
 | 
			
		||||
    // convert animation data to aiAnimation et al
 | 
			
		||||
    void ConvertAnimations();
 | 
			
		||||
 | 
			
		||||
    // ------------------------------------------------------------------------------------------------
 | 
			
		||||
    // takes a fbx node name and returns the identifier to be used in the assimp output scene.
 | 
			
		||||
    // the function is guaranteed to provide consistent results over multiple invocations
 | 
			
		||||
    // UNLESS RenameNode() is called for a particular node name.
 | 
			
		||||
    std::string FixNodeName(const std::string& name);
 | 
			
		||||
    std::string FixAnimMeshName(const std::string& name);
 | 
			
		||||
 | 
			
		||||
    typedef std::map<const AnimationCurveNode*, const AnimationLayer*> LayerMap;
 | 
			
		||||
 | 
			
		||||
    // XXX: better use multi_map ..
 | 
			
		||||
    typedef std::map<std::string, std::vector<const AnimationCurveNode*> > NodeMap;
 | 
			
		||||
 | 
			
		||||
    // ------------------------------------------------------------------------------------------------
 | 
			
		||||
    void ConvertAnimationStack(const AnimationStack& st);
 | 
			
		||||
 | 
			
		||||
    // ------------------------------------------------------------------------------------------------
 | 
			
		||||
    void ProcessMorphAnimDatas(std::map<std::string, morphAnimData*>* morphAnimDatas, const BlendShapeChannel* bsc, const AnimationCurveNode* node);
 | 
			
		||||
 | 
			
		||||
    // ------------------------------------------------------------------------------------------------
 | 
			
		||||
    void GenerateNodeAnimations(std::vector<aiNodeAnim*>& node_anims,
 | 
			
		||||
        const std::string& fixed_name,
 | 
			
		||||
        const std::vector<const AnimationCurveNode*>& curves,
 | 
			
		||||
        const LayerMap& layer_map,
 | 
			
		||||
        int64_t start, int64_t stop,
 | 
			
		||||
        double& max_time,
 | 
			
		||||
        double& min_time);
 | 
			
		||||
 | 
			
		||||
    // ------------------------------------------------------------------------------------------------
 | 
			
		||||
    bool IsRedundantAnimationData(const Model& target,
 | 
			
		||||
        TransformationComp comp,
 | 
			
		||||
        const std::vector<const AnimationCurveNode*>& curves);
 | 
			
		||||
 | 
			
		||||
    // ------------------------------------------------------------------------------------------------
 | 
			
		||||
    aiNodeAnim* GenerateRotationNodeAnim(const std::string& name,
 | 
			
		||||
        const Model& target,
 | 
			
		||||
        const std::vector<const AnimationCurveNode*>& curves,
 | 
			
		||||
        const LayerMap& layer_map,
 | 
			
		||||
        int64_t start, int64_t stop,
 | 
			
		||||
        double& max_time,
 | 
			
		||||
        double& min_time);
 | 
			
		||||
 | 
			
		||||
    // ------------------------------------------------------------------------------------------------
 | 
			
		||||
    aiNodeAnim* GenerateScalingNodeAnim(const std::string& name,
 | 
			
		||||
        const Model& /*target*/,
 | 
			
		||||
        const std::vector<const AnimationCurveNode*>& curves,
 | 
			
		||||
        const LayerMap& layer_map,
 | 
			
		||||
        int64_t start, int64_t stop,
 | 
			
		||||
        double& max_time,
 | 
			
		||||
        double& min_time);
 | 
			
		||||
 | 
			
		||||
    // ------------------------------------------------------------------------------------------------
 | 
			
		||||
    aiNodeAnim* GenerateTranslationNodeAnim(const std::string& name,
 | 
			
		||||
        const Model& /*target*/,
 | 
			
		||||
        const std::vector<const AnimationCurveNode*>& curves,
 | 
			
		||||
        const LayerMap& layer_map,
 | 
			
		||||
        int64_t start, int64_t stop,
 | 
			
		||||
        double& max_time,
 | 
			
		||||
        double& min_time,
 | 
			
		||||
        bool inverse = false);
 | 
			
		||||
 | 
			
		||||
    // ------------------------------------------------------------------------------------------------
 | 
			
		||||
    // generate node anim, extracting only Rotation, Scaling and Translation from the given chain
 | 
			
		||||
    aiNodeAnim* GenerateSimpleNodeAnim(const std::string& name,
 | 
			
		||||
        const Model& target,
 | 
			
		||||
        NodeMap::const_iterator chain[TransformationComp_MAXIMUM],
 | 
			
		||||
        NodeMap::const_iterator iter_end,
 | 
			
		||||
        const LayerMap& layer_map,
 | 
			
		||||
        int64_t start, int64_t stop,
 | 
			
		||||
        double& max_time,
 | 
			
		||||
        double& min_time,
 | 
			
		||||
        bool reverse_order = false);
 | 
			
		||||
 | 
			
		||||
    // key (time), value, mapto (component index)
 | 
			
		||||
    typedef std::tuple<std::shared_ptr<KeyTimeList>, std::shared_ptr<KeyValueList>, unsigned int > KeyFrameList;
 | 
			
		||||
    typedef std::vector<KeyFrameList> KeyFrameListList;
 | 
			
		||||
 | 
			
		||||
    // ------------------------------------------------------------------------------------------------
 | 
			
		||||
    KeyFrameListList GetKeyframeList(const std::vector<const AnimationCurveNode*>& nodes, int64_t start, int64_t stop);
 | 
			
		||||
 | 
			
		||||
    // ------------------------------------------------------------------------------------------------
 | 
			
		||||
    KeyTimeList GetKeyTimeList(const KeyFrameListList& inputs);
 | 
			
		||||
 | 
			
		||||
    // ------------------------------------------------------------------------------------------------
 | 
			
		||||
    void InterpolateKeys(aiVectorKey* valOut, const KeyTimeList& keys, const KeyFrameListList& inputs,
 | 
			
		||||
        const aiVector3D& def_value,
 | 
			
		||||
        double& max_time,
 | 
			
		||||
        double& min_time);
 | 
			
		||||
 | 
			
		||||
    // ------------------------------------------------------------------------------------------------
 | 
			
		||||
    void InterpolateKeys(aiQuatKey* valOut, const KeyTimeList& keys, const KeyFrameListList& inputs,
 | 
			
		||||
        const aiVector3D& def_value,
 | 
			
		||||
        double& maxTime,
 | 
			
		||||
        double& minTime,
 | 
			
		||||
        Model::RotOrder order);
 | 
			
		||||
 | 
			
		||||
    // ------------------------------------------------------------------------------------------------
 | 
			
		||||
    void ConvertTransformOrder_TRStoSRT(aiQuatKey* out_quat, aiVectorKey* out_scale,
 | 
			
		||||
        aiVectorKey* out_translation,
 | 
			
		||||
        const KeyFrameListList& scaling,
 | 
			
		||||
        const KeyFrameListList& translation,
 | 
			
		||||
        const KeyFrameListList& rotation,
 | 
			
		||||
        const KeyTimeList& times,
 | 
			
		||||
        double& maxTime,
 | 
			
		||||
        double& minTime,
 | 
			
		||||
        Model::RotOrder order,
 | 
			
		||||
        const aiVector3D& def_scale,
 | 
			
		||||
        const aiVector3D& def_translate,
 | 
			
		||||
        const aiVector3D& def_rotation);
 | 
			
		||||
 | 
			
		||||
    // ------------------------------------------------------------------------------------------------
 | 
			
		||||
    // euler xyz -> quat
 | 
			
		||||
    aiQuaternion EulerToQuaternion(const aiVector3D& rot, Model::RotOrder order);
 | 
			
		||||
 | 
			
		||||
    // ------------------------------------------------------------------------------------------------
 | 
			
		||||
    void ConvertScaleKeys(aiNodeAnim* na, const std::vector<const AnimationCurveNode*>& nodes, const LayerMap& /*layers*/,
 | 
			
		||||
        int64_t start, int64_t stop,
 | 
			
		||||
        double& maxTime,
 | 
			
		||||
        double& minTime);
 | 
			
		||||
 | 
			
		||||
    // ------------------------------------------------------------------------------------------------
 | 
			
		||||
    void ConvertTranslationKeys(aiNodeAnim* na, const std::vector<const AnimationCurveNode*>& nodes,
 | 
			
		||||
        const LayerMap& /*layers*/,
 | 
			
		||||
        int64_t start, int64_t stop,
 | 
			
		||||
        double& maxTime,
 | 
			
		||||
        double& minTime);
 | 
			
		||||
 | 
			
		||||
    // ------------------------------------------------------------------------------------------------
 | 
			
		||||
    void ConvertRotationKeys(aiNodeAnim* na, const std::vector<const AnimationCurveNode*>& nodes,
 | 
			
		||||
        const LayerMap& /*layers*/,
 | 
			
		||||
        int64_t start, int64_t stop,
 | 
			
		||||
        double& maxTime,
 | 
			
		||||
        double& minTime,
 | 
			
		||||
        Model::RotOrder order);
 | 
			
		||||
 | 
			
		||||
    void ConvertGlobalSettings();
 | 
			
		||||
 | 
			
		||||
    // ------------------------------------------------------------------------------------------------
 | 
			
		||||
    // copy generated meshes, animations, lights, cameras and textures to the output scene
 | 
			
		||||
    void TransferDataToScene();
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    // 0: not assigned yet, others: index is value - 1
 | 
			
		||||
    unsigned int defaultMaterialIndex;
 | 
			
		||||
 | 
			
		||||
    std::vector<aiMesh*> meshes;
 | 
			
		||||
    std::vector<aiMaterial*> materials;
 | 
			
		||||
    std::vector<aiAnimation*> animations;
 | 
			
		||||
    std::vector<aiLight*> lights;
 | 
			
		||||
    std::vector<aiCamera*> cameras;
 | 
			
		||||
    std::vector<aiTexture*> textures;
 | 
			
		||||
 | 
			
		||||
    using MaterialMap = std::map<const Material*, unsigned int>;
 | 
			
		||||
    MaterialMap materials_converted;
 | 
			
		||||
 | 
			
		||||
    using VideoMap = std::map<const Video*, unsigned int>;
 | 
			
		||||
    VideoMap textures_converted;
 | 
			
		||||
 | 
			
		||||
    using MeshMap = std::map<const Geometry*, std::vector<unsigned int> >;
 | 
			
		||||
    MeshMap meshes_converted;
 | 
			
		||||
 | 
			
		||||
    // fixed node name -> which trafo chain components have animations?
 | 
			
		||||
    using NodeAnimBitMap = std::map<std::string, unsigned int> ;
 | 
			
		||||
    NodeAnimBitMap node_anim_chain_bits;
 | 
			
		||||
 | 
			
		||||
    // number of nodes with the same name
 | 
			
		||||
    using NodeNameCache = std::unordered_map<std::string, unsigned int>;
 | 
			
		||||
    NodeNameCache mNodeNames;
 | 
			
		||||
 | 
			
		||||
    double anim_fps;
 | 
			
		||||
 | 
			
		||||
    aiScene* const out;
 | 
			
		||||
    const FBX::Document& doc;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif // INCLUDED_AI_FBX_CONVERTER_H
 | 
			
		||||
							
								
								
									
										213
									
								
								thirdparty/assimp/code/FBX/FBXDeformer.cpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										213
									
								
								thirdparty/assimp/code/FBX/FBXDeformer.cpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,213 @@
 | 
			
		||||
/*
 | 
			
		||||
Open Asset Import Library (assimp)
 | 
			
		||||
----------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
Copyright (c) 2006-2019, 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  FBXNoteAttribute.cpp
 | 
			
		||||
 *  @brief Assimp::FBX::NodeAttribute (and subclasses) implementation
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef ASSIMP_BUILD_NO_FBX_IMPORTER
 | 
			
		||||
 | 
			
		||||
#include "FBXParser.h"
 | 
			
		||||
#include "FBXDocument.h"
 | 
			
		||||
#include "FBXMeshGeometry.h"
 | 
			
		||||
#include "FBXImporter.h"
 | 
			
		||||
#include "FBXDocumentUtil.h"
 | 
			
		||||
 | 
			
		||||
namespace Assimp {
 | 
			
		||||
namespace FBX {
 | 
			
		||||
 | 
			
		||||
using namespace Util;
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
Deformer::Deformer(uint64_t id, const Element& element, const Document& doc, const std::string& name)
 | 
			
		||||
    : Object(id,element,name)
 | 
			
		||||
{
 | 
			
		||||
    const Scope& sc = GetRequiredScope(element);
 | 
			
		||||
 | 
			
		||||
    const std::string& classname = ParseTokenAsString(GetRequiredToken(element,2));
 | 
			
		||||
    props = GetPropertyTable(doc,"Deformer.Fbx" + classname,element,sc,true);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
Deformer::~Deformer()
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
Cluster::Cluster(uint64_t id, const Element& element, const Document& doc, const std::string& name)
 | 
			
		||||
: Deformer(id,element,doc,name)
 | 
			
		||||
, node()
 | 
			
		||||
{
 | 
			
		||||
    const Scope& sc = GetRequiredScope(element);
 | 
			
		||||
 | 
			
		||||
    const Element* const Indexes = sc["Indexes"];
 | 
			
		||||
    const Element* const Weights = sc["Weights"];
 | 
			
		||||
 | 
			
		||||
    const Element& Transform = GetRequiredElement(sc,"Transform",&element);
 | 
			
		||||
    const Element& TransformLink = GetRequiredElement(sc,"TransformLink",&element);
 | 
			
		||||
 | 
			
		||||
    transform = ReadMatrix(Transform);
 | 
			
		||||
    transformLink = ReadMatrix(TransformLink);
 | 
			
		||||
 | 
			
		||||
    // it is actually possible that there be Deformer's with no weights
 | 
			
		||||
    if (!!Indexes != !!Weights) {
 | 
			
		||||
        DOMError("either Indexes or Weights are missing from Cluster",&element);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(Indexes) {
 | 
			
		||||
        ParseVectorDataArray(indices,*Indexes);
 | 
			
		||||
        ParseVectorDataArray(weights,*Weights);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(indices.size() != weights.size()) {
 | 
			
		||||
        DOMError("sizes of index and weight array don't match up",&element);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // read assigned node
 | 
			
		||||
    const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID(),"Model");
 | 
			
		||||
    for(const Connection* con : conns) {
 | 
			
		||||
        const Model* const mod = ProcessSimpleConnection<Model>(*con, false, "Model -> Cluster", element);
 | 
			
		||||
        if(mod) {
 | 
			
		||||
            node = mod;
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!node) {
 | 
			
		||||
        DOMError("failed to read target Node for Cluster",&element);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
Cluster::~Cluster()
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
Skin::Skin(uint64_t id, const Element& element, const Document& doc, const std::string& name)
 | 
			
		||||
: Deformer(id,element,doc,name)
 | 
			
		||||
, accuracy( 0.0f ) {
 | 
			
		||||
    const Scope& sc = GetRequiredScope(element);
 | 
			
		||||
 | 
			
		||||
    const Element* const Link_DeformAcuracy = sc["Link_DeformAcuracy"];
 | 
			
		||||
    if(Link_DeformAcuracy) {
 | 
			
		||||
        accuracy = ParseTokenAsFloat(GetRequiredToken(*Link_DeformAcuracy,0));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // resolve assigned clusters
 | 
			
		||||
    const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID(),"Deformer");
 | 
			
		||||
 | 
			
		||||
    clusters.reserve(conns.size());
 | 
			
		||||
    for(const Connection* con : conns) {
 | 
			
		||||
 | 
			
		||||
        const Cluster* const cluster = ProcessSimpleConnection<Cluster>(*con, false, "Cluster -> Skin", element);
 | 
			
		||||
        if(cluster) {
 | 
			
		||||
            clusters.push_back(cluster);
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
Skin::~Skin()
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
BlendShape::BlendShape(uint64_t id, const Element& element, const Document& doc, const std::string& name)
 | 
			
		||||
    : Deformer(id, element, doc, name)
 | 
			
		||||
{
 | 
			
		||||
    const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID(), "Deformer");
 | 
			
		||||
    blendShapeChannels.reserve(conns.size());
 | 
			
		||||
    for (const Connection* con : conns) {
 | 
			
		||||
        const BlendShapeChannel* const bspc = ProcessSimpleConnection<BlendShapeChannel>(*con, false, "BlendShapeChannel -> BlendShape", element);
 | 
			
		||||
        if (bspc) {
 | 
			
		||||
            blendShapeChannels.push_back(bspc);
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
BlendShape::~BlendShape()
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
BlendShapeChannel::BlendShapeChannel(uint64_t id, const Element& element, const Document& doc, const std::string& name)
 | 
			
		||||
    : Deformer(id, element, doc, name)
 | 
			
		||||
{
 | 
			
		||||
    const Scope& sc = GetRequiredScope(element);
 | 
			
		||||
    const Element* const DeformPercent = sc["DeformPercent"];
 | 
			
		||||
    if (DeformPercent) {
 | 
			
		||||
        percent = ParseTokenAsFloat(GetRequiredToken(*DeformPercent, 0));
 | 
			
		||||
    }
 | 
			
		||||
    const Element* const FullWeights = sc["FullWeights"];
 | 
			
		||||
    if (FullWeights) {
 | 
			
		||||
        ParseVectorDataArray(fullWeights, *FullWeights);
 | 
			
		||||
    }
 | 
			
		||||
    const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID(), "Geometry");
 | 
			
		||||
    shapeGeometries.reserve(conns.size());
 | 
			
		||||
    for (const Connection* con : conns) {
 | 
			
		||||
        const ShapeGeometry* const sg = ProcessSimpleConnection<ShapeGeometry>(*con, false, "Shape -> BlendShapeChannel", element);
 | 
			
		||||
        if (sg) {
 | 
			
		||||
            shapeGeometries.push_back(sg);
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
BlendShapeChannel::~BlendShapeChannel()
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										718
									
								
								thirdparty/assimp/code/FBX/FBXDocument.cpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										718
									
								
								thirdparty/assimp/code/FBX/FBXDocument.cpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,718 @@
 | 
			
		||||
/*
 | 
			
		||||
Open Asset Import Library (assimp)
 | 
			
		||||
----------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
Copyright (c) 2006-2019, 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  FBXDocument.cpp
 | 
			
		||||
 *  @brief Implementation of the FBX DOM classes
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef ASSIMP_BUILD_NO_FBX_IMPORTER
 | 
			
		||||
 | 
			
		||||
#include "FBXDocument.h"
 | 
			
		||||
#include "FBXMeshGeometry.h"
 | 
			
		||||
#include "FBXParser.h"
 | 
			
		||||
#include "FBXUtil.h"
 | 
			
		||||
#include "FBXImporter.h"
 | 
			
		||||
#include "FBXImportSettings.h"
 | 
			
		||||
#include "FBXDocumentUtil.h"
 | 
			
		||||
#include "FBXProperties.h"
 | 
			
		||||
 | 
			
		||||
#include <memory>
 | 
			
		||||
#include <functional>
 | 
			
		||||
#include <map>
 | 
			
		||||
 | 
			
		||||
namespace Assimp {
 | 
			
		||||
namespace FBX {
 | 
			
		||||
 | 
			
		||||
using namespace Util;
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
LazyObject::LazyObject(uint64_t id, const Element& element, const Document& doc)
 | 
			
		||||
: doc(doc)
 | 
			
		||||
, element(element)
 | 
			
		||||
, id(id)
 | 
			
		||||
, flags() {
 | 
			
		||||
    // empty
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
LazyObject::~LazyObject()
 | 
			
		||||
{
 | 
			
		||||
    // empty
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
const Object* LazyObject::Get(bool dieOnError)
 | 
			
		||||
{
 | 
			
		||||
    if(IsBeingConstructed() || FailedToConstruct()) {
 | 
			
		||||
        return nullptr;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (object.get()) {
 | 
			
		||||
        return object.get();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const Token& key = element.KeyToken();
 | 
			
		||||
    const TokenList& tokens = element.Tokens();
 | 
			
		||||
 | 
			
		||||
    if(tokens.size() < 3) {
 | 
			
		||||
        DOMError("expected at least 3 tokens: id, name and class tag",&element);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const char* err;
 | 
			
		||||
    std::string name = ParseTokenAsString(*tokens[1],err);
 | 
			
		||||
    if (err) {
 | 
			
		||||
        DOMError(err,&element);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // small fix for binary reading: binary fbx files don't use
 | 
			
		||||
    // prefixes such as Model:: in front of their names. The
 | 
			
		||||
    // loading code expects this at many places, though!
 | 
			
		||||
    // so convert the binary representation (a 0x0001) to the
 | 
			
		||||
    // double colon notation.
 | 
			
		||||
    if(tokens[1]->IsBinary()) {
 | 
			
		||||
        for (size_t i = 0; i < name.length(); ++i) {
 | 
			
		||||
            if (name[i] == 0x0 && name[i+1] == 0x1) {
 | 
			
		||||
                name = name.substr(i+2) + "::" + name.substr(0,i);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const std::string classtag = ParseTokenAsString(*tokens[2],err);
 | 
			
		||||
    if (err) {
 | 
			
		||||
        DOMError(err,&element);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // prevent recursive calls
 | 
			
		||||
    flags |= BEING_CONSTRUCTED;
 | 
			
		||||
 | 
			
		||||
    try {
 | 
			
		||||
        // this needs to be relatively fast since it happens a lot,
 | 
			
		||||
        // so avoid constructing strings all the time.
 | 
			
		||||
        const char* obtype = key.begin();
 | 
			
		||||
        const size_t length = static_cast<size_t>(key.end()-key.begin());
 | 
			
		||||
 | 
			
		||||
        // For debugging
 | 
			
		||||
        //dumpObjectClassInfo( objtype, classtag );
 | 
			
		||||
 | 
			
		||||
        if (!strncmp(obtype,"Geometry",length)) {
 | 
			
		||||
            if (!strcmp(classtag.c_str(),"Mesh")) {
 | 
			
		||||
                object.reset(new MeshGeometry(id,element,name,doc));
 | 
			
		||||
            }
 | 
			
		||||
            if (!strcmp(classtag.c_str(), "Shape")) {
 | 
			
		||||
                object.reset(new ShapeGeometry(id, element, name, doc));
 | 
			
		||||
            }
 | 
			
		||||
            if (!strcmp(classtag.c_str(), "Line")) {
 | 
			
		||||
                object.reset(new LineGeometry(id, element, name, doc));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        else if (!strncmp(obtype,"NodeAttribute",length)) {
 | 
			
		||||
            if (!strcmp(classtag.c_str(),"Camera")) {
 | 
			
		||||
                object.reset(new Camera(id,element,doc,name));
 | 
			
		||||
            }
 | 
			
		||||
            else if (!strcmp(classtag.c_str(),"CameraSwitcher")) {
 | 
			
		||||
                object.reset(new CameraSwitcher(id,element,doc,name));
 | 
			
		||||
            }
 | 
			
		||||
            else if (!strcmp(classtag.c_str(),"Light")) {
 | 
			
		||||
                object.reset(new Light(id,element,doc,name));
 | 
			
		||||
            }
 | 
			
		||||
            else if (!strcmp(classtag.c_str(),"Null")) {
 | 
			
		||||
                object.reset(new Null(id,element,doc,name));
 | 
			
		||||
            }
 | 
			
		||||
            else if (!strcmp(classtag.c_str(),"LimbNode")) {
 | 
			
		||||
                object.reset(new LimbNode(id,element,doc,name));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        else if (!strncmp(obtype,"Deformer",length)) {
 | 
			
		||||
            if (!strcmp(classtag.c_str(),"Cluster")) {
 | 
			
		||||
                object.reset(new Cluster(id,element,doc,name));
 | 
			
		||||
            }
 | 
			
		||||
            else if (!strcmp(classtag.c_str(),"Skin")) {
 | 
			
		||||
                object.reset(new Skin(id,element,doc,name));
 | 
			
		||||
            }
 | 
			
		||||
            else if (!strcmp(classtag.c_str(), "BlendShape")) {
 | 
			
		||||
                object.reset(new BlendShape(id, element, doc, name));
 | 
			
		||||
            }
 | 
			
		||||
            else if (!strcmp(classtag.c_str(), "BlendShapeChannel")) {
 | 
			
		||||
                object.reset(new BlendShapeChannel(id, element, doc, name));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        else if ( !strncmp( obtype, "Model", length ) ) {
 | 
			
		||||
            // FK and IK effectors are not supported
 | 
			
		||||
            if ( strcmp( classtag.c_str(), "IKEffector" ) && strcmp( classtag.c_str(), "FKEffector" ) ) {
 | 
			
		||||
                object.reset( new Model( id, element, doc, name ) );
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        else if (!strncmp(obtype,"Material",length)) {
 | 
			
		||||
            object.reset(new Material(id,element,doc,name));
 | 
			
		||||
        }
 | 
			
		||||
        else if (!strncmp(obtype,"Texture",length)) {
 | 
			
		||||
            object.reset(new Texture(id,element,doc,name));
 | 
			
		||||
        }
 | 
			
		||||
        else if (!strncmp(obtype,"LayeredTexture",length)) {
 | 
			
		||||
            object.reset(new LayeredTexture(id,element,doc,name));
 | 
			
		||||
        }
 | 
			
		||||
        else if (!strncmp(obtype,"Video",length)) {
 | 
			
		||||
            object.reset(new Video(id,element,doc,name));
 | 
			
		||||
        }
 | 
			
		||||
        else if (!strncmp(obtype,"AnimationStack",length)) {
 | 
			
		||||
            object.reset(new AnimationStack(id,element,name,doc));
 | 
			
		||||
        }
 | 
			
		||||
        else if (!strncmp(obtype,"AnimationLayer",length)) {
 | 
			
		||||
            object.reset(new AnimationLayer(id,element,name,doc));
 | 
			
		||||
        }
 | 
			
		||||
        // note: order matters for these two
 | 
			
		||||
        else if (!strncmp(obtype,"AnimationCurve",length)) {
 | 
			
		||||
            object.reset(new AnimationCurve(id,element,name,doc));
 | 
			
		||||
        }
 | 
			
		||||
        else if (!strncmp(obtype,"AnimationCurveNode",length)) {
 | 
			
		||||
            object.reset(new AnimationCurveNode(id,element,name,doc));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    catch(std::exception& ex) {
 | 
			
		||||
        flags &= ~BEING_CONSTRUCTED;
 | 
			
		||||
        flags |= FAILED_TO_CONSTRUCT;
 | 
			
		||||
 | 
			
		||||
        if(dieOnError || doc.Settings().strictMode) {
 | 
			
		||||
            throw;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // note: the error message is already formatted, so raw logging is ok
 | 
			
		||||
        if(!DefaultLogger::isNullLogger()) {
 | 
			
		||||
            ASSIMP_LOG_ERROR(ex.what());
 | 
			
		||||
        }
 | 
			
		||||
        return NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!object.get()) {
 | 
			
		||||
        //DOMError("failed to convert element to DOM object, class: " + classtag + ", name: " + name,&element);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    flags &= ~BEING_CONSTRUCTED;
 | 
			
		||||
    return object.get();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
Object::Object(uint64_t id, const Element& element, const std::string& name)
 | 
			
		||||
: element(element)
 | 
			
		||||
, name(name)
 | 
			
		||||
, id(id)
 | 
			
		||||
{
 | 
			
		||||
    // empty
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
Object::~Object()
 | 
			
		||||
{
 | 
			
		||||
    // empty
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
FileGlobalSettings::FileGlobalSettings(const Document& doc, std::shared_ptr<const PropertyTable> props)
 | 
			
		||||
: props(props)
 | 
			
		||||
, doc(doc)
 | 
			
		||||
{
 | 
			
		||||
    // empty
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
FileGlobalSettings::~FileGlobalSettings()
 | 
			
		||||
{
 | 
			
		||||
    // empty
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
Document::Document(const Parser& parser, const ImportSettings& settings)
 | 
			
		||||
: settings(settings)
 | 
			
		||||
, parser(parser)
 | 
			
		||||
{
 | 
			
		||||
    // Cannot use array default initialization syntax because vc8 fails on it
 | 
			
		||||
    for (auto &timeStamp : creationTimeStamp) {
 | 
			
		||||
        timeStamp = 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ReadHeader();
 | 
			
		||||
    ReadPropertyTemplates();
 | 
			
		||||
 | 
			
		||||
    ReadGlobalSettings();
 | 
			
		||||
 | 
			
		||||
    // This order is important, connections need parsed objects to check
 | 
			
		||||
    // whether connections are ok or not. Objects may not be evaluated yet,
 | 
			
		||||
    // though, since this may require valid connections.
 | 
			
		||||
    ReadObjects();
 | 
			
		||||
    ReadConnections();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
Document::~Document()
 | 
			
		||||
{
 | 
			
		||||
    for(ObjectMap::value_type& v : objects) {
 | 
			
		||||
        delete v.second;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for(ConnectionMap::value_type& v : src_connections) {
 | 
			
		||||
        delete v.second;
 | 
			
		||||
    }
 | 
			
		||||
    // |dest_connections| contain the same Connection objects as the |src_connections|
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
static const unsigned int LowerSupportedVersion = 7100;
 | 
			
		||||
static const unsigned int UpperSupportedVersion = 7400;
 | 
			
		||||
 | 
			
		||||
void Document::ReadHeader() {
 | 
			
		||||
    // Read ID objects from "Objects" section
 | 
			
		||||
    const Scope& sc = parser.GetRootScope();
 | 
			
		||||
    const Element* const ehead = sc["FBXHeaderExtension"];
 | 
			
		||||
    if(!ehead || !ehead->Compound()) {
 | 
			
		||||
        DOMError("no FBXHeaderExtension dictionary found");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const Scope& shead = *ehead->Compound();
 | 
			
		||||
    fbxVersion = ParseTokenAsInt(GetRequiredToken(GetRequiredElement(shead,"FBXVersion",ehead),0));
 | 
			
		||||
 | 
			
		||||
    // While we may have some success with newer files, we don't support
 | 
			
		||||
    // the older 6.n fbx format
 | 
			
		||||
    if(fbxVersion < LowerSupportedVersion ) {
 | 
			
		||||
        DOMError("unsupported, old format version, supported are only FBX 2011, FBX 2012 and FBX 2013");
 | 
			
		||||
    }
 | 
			
		||||
    if(fbxVersion > UpperSupportedVersion ) {
 | 
			
		||||
        if(Settings().strictMode) {
 | 
			
		||||
            DOMError("unsupported, newer format version, supported are only FBX 2011, FBX 2012 and FBX 2013"
 | 
			
		||||
                " (turn off strict mode to try anyhow) ");
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
            DOMWarning("unsupported, newer format version, supported are only FBX 2011, FBX 2012 and FBX 2013,"
 | 
			
		||||
                " trying to read it nevertheless");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const Element* const ecreator = shead["Creator"];
 | 
			
		||||
    if(ecreator) {
 | 
			
		||||
        creator = ParseTokenAsString(GetRequiredToken(*ecreator,0));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const Element* const etimestamp = shead["CreationTimeStamp"];
 | 
			
		||||
    if(etimestamp && etimestamp->Compound()) {
 | 
			
		||||
        const Scope& stimestamp = *etimestamp->Compound();
 | 
			
		||||
        creationTimeStamp[0] = ParseTokenAsInt(GetRequiredToken(GetRequiredElement(stimestamp,"Year"),0));
 | 
			
		||||
        creationTimeStamp[1] = ParseTokenAsInt(GetRequiredToken(GetRequiredElement(stimestamp,"Month"),0));
 | 
			
		||||
        creationTimeStamp[2] = ParseTokenAsInt(GetRequiredToken(GetRequiredElement(stimestamp,"Day"),0));
 | 
			
		||||
        creationTimeStamp[3] = ParseTokenAsInt(GetRequiredToken(GetRequiredElement(stimestamp,"Hour"),0));
 | 
			
		||||
        creationTimeStamp[4] = ParseTokenAsInt(GetRequiredToken(GetRequiredElement(stimestamp,"Minute"),0));
 | 
			
		||||
        creationTimeStamp[5] = ParseTokenAsInt(GetRequiredToken(GetRequiredElement(stimestamp,"Second"),0));
 | 
			
		||||
        creationTimeStamp[6] = ParseTokenAsInt(GetRequiredToken(GetRequiredElement(stimestamp,"Millisecond"),0));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
void Document::ReadGlobalSettings()
 | 
			
		||||
{
 | 
			
		||||
    const Scope& sc = parser.GetRootScope();
 | 
			
		||||
    const Element* const ehead = sc["GlobalSettings"];
 | 
			
		||||
    if ( nullptr == ehead || !ehead->Compound() ) {
 | 
			
		||||
        DOMWarning( "no GlobalSettings dictionary found" );
 | 
			
		||||
        globals.reset(new FileGlobalSettings(*this, std::make_shared<const PropertyTable>()));
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::shared_ptr<const PropertyTable> props = GetPropertyTable( *this, "", *ehead, *ehead->Compound(), true );
 | 
			
		||||
 | 
			
		||||
    //double v = PropertyGet<float>( *props.get(), std::string("UnitScaleFactor"), 1.0 );
 | 
			
		||||
 | 
			
		||||
    if(!props) {
 | 
			
		||||
        DOMError("GlobalSettings dictionary contains no property table");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    globals.reset(new FileGlobalSettings(*this, props));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
void Document::ReadObjects()
 | 
			
		||||
{
 | 
			
		||||
    // read ID objects from "Objects" section
 | 
			
		||||
    const Scope& sc = parser.GetRootScope();
 | 
			
		||||
    const Element* const eobjects = sc["Objects"];
 | 
			
		||||
    if(!eobjects || !eobjects->Compound()) {
 | 
			
		||||
        DOMError("no Objects dictionary found");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // 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);
 | 
			
		||||
 | 
			
		||||
    const Scope& sobjects = *eobjects->Compound();
 | 
			
		||||
    for(const ElementMap::value_type& el : sobjects.Elements()) {
 | 
			
		||||
 | 
			
		||||
        // extract ID
 | 
			
		||||
        const TokenList& tok = el.second->Tokens();
 | 
			
		||||
 | 
			
		||||
        if (tok.empty()) {
 | 
			
		||||
            DOMError("expected ID after object key",el.second);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const char* err;
 | 
			
		||||
        const uint64_t id = ParseTokenAsID(*tok[0], err);
 | 
			
		||||
        if(err) {
 | 
			
		||||
            DOMError(err,el.second);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // id=0 is normally implicit
 | 
			
		||||
        if(id == 0L) {
 | 
			
		||||
            DOMError("encountered object with implicitly defined id 0",el.second);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if(objects.find(id) != objects.end()) {
 | 
			
		||||
            DOMWarning("encountered duplicate object id, ignoring first occurrence",el.second);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        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")) {
 | 
			
		||||
            animationStacks.push_back(id);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
void Document::ReadPropertyTemplates()
 | 
			
		||||
{
 | 
			
		||||
    const Scope& sc = parser.GetRootScope();
 | 
			
		||||
    // read property templates from "Definitions" section
 | 
			
		||||
    const Element* const edefs = sc["Definitions"];
 | 
			
		||||
    if(!edefs || !edefs->Compound()) {
 | 
			
		||||
        DOMWarning("no Definitions dictionary found");
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const Scope& sdefs = *edefs->Compound();
 | 
			
		||||
    const ElementCollection otypes = sdefs.GetCollection("ObjectType");
 | 
			
		||||
    for(ElementMap::const_iterator it = otypes.first; it != otypes.second; ++it) {
 | 
			
		||||
        const Element& el = *(*it).second;
 | 
			
		||||
        const Scope* sc = el.Compound();
 | 
			
		||||
        if(!sc) {
 | 
			
		||||
            DOMWarning("expected nested scope in ObjectType, ignoring",&el);
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const TokenList& tok = el.Tokens();
 | 
			
		||||
        if(tok.empty()) {
 | 
			
		||||
            DOMWarning("expected name for ObjectType element, ignoring",&el);
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const std::string& oname = ParseTokenAsString(*tok[0]);
 | 
			
		||||
 | 
			
		||||
        const ElementCollection templs = sc->GetCollection("PropertyTemplate");
 | 
			
		||||
        for(ElementMap::const_iterator it = templs.first; it != templs.second; ++it) {
 | 
			
		||||
            const Element& el = *(*it).second;
 | 
			
		||||
            const Scope* sc = el.Compound();
 | 
			
		||||
            if(!sc) {
 | 
			
		||||
                DOMWarning("expected nested scope in PropertyTemplate, ignoring",&el);
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            const TokenList& tok = el.Tokens();
 | 
			
		||||
            if(tok.empty()) {
 | 
			
		||||
                DOMWarning("expected name for PropertyTemplate element, ignoring",&el);
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            const std::string& pname = ParseTokenAsString(*tok[0]);
 | 
			
		||||
 | 
			
		||||
            const Element* Properties70 = (*sc)["Properties70"];
 | 
			
		||||
            if(Properties70) {
 | 
			
		||||
                std::shared_ptr<const PropertyTable> props = std::make_shared<const PropertyTable>(
 | 
			
		||||
                    *Properties70,std::shared_ptr<const PropertyTable>(static_cast<const PropertyTable*>(NULL))
 | 
			
		||||
                );
 | 
			
		||||
 | 
			
		||||
                templates[oname+"."+pname] = props;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
void Document::ReadConnections()
 | 
			
		||||
{
 | 
			
		||||
    const Scope& sc = parser.GetRootScope();
 | 
			
		||||
    // read property templates from "Definitions" section
 | 
			
		||||
    const Element* const econns = sc["Connections"];
 | 
			
		||||
    if(!econns || !econns->Compound()) {
 | 
			
		||||
        DOMError("no Connections dictionary found");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    uint64_t insertionOrder = 0l;
 | 
			
		||||
    const Scope& sconns = *econns->Compound();
 | 
			
		||||
    const ElementCollection conns = sconns.GetCollection("C");
 | 
			
		||||
    for(ElementMap::const_iterator it = conns.first; it != conns.second; ++it) {
 | 
			
		||||
        const Element& el = *(*it).second;
 | 
			
		||||
        const std::string& type = ParseTokenAsString(GetRequiredToken(el,0));
 | 
			
		||||
 | 
			
		||||
        // PP = property-property connection, ignored for now
 | 
			
		||||
        // (tokens: "PP", ID1, "Property1", ID2, "Property2")
 | 
			
		||||
        if ( type == "PP" ) {
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const uint64_t src = ParseTokenAsID(GetRequiredToken(el,1));
 | 
			
		||||
        const uint64_t dest = ParseTokenAsID(GetRequiredToken(el,2));
 | 
			
		||||
 | 
			
		||||
        // OO = object-object connection
 | 
			
		||||
        // OP = object-property connection, in which case the destination property follows the object ID
 | 
			
		||||
        const std::string& prop = (type == "OP" ? ParseTokenAsString(GetRequiredToken(el,3)) : "");
 | 
			
		||||
 | 
			
		||||
        if(objects.find(src) == objects.end()) {
 | 
			
		||||
            DOMWarning("source object for connection does not exist",&el);
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // dest may be 0 (root node) but we added a dummy object before
 | 
			
		||||
        if(objects.find(dest) == objects.end()) {
 | 
			
		||||
            DOMWarning("destination object for connection does not exist",&el);
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // add new connection
 | 
			
		||||
        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));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
const std::vector<const AnimationStack*>& Document::AnimationStacks() const
 | 
			
		||||
{
 | 
			
		||||
    if (!animationStacksResolved.empty() || animationStacks.empty()) {
 | 
			
		||||
        return animationStacksResolved;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    animationStacksResolved.reserve(animationStacks.size());
 | 
			
		||||
    for(uint64_t id : animationStacks) {
 | 
			
		||||
        LazyObject* const lazy = GetObject(id);
 | 
			
		||||
        const AnimationStack* stack;
 | 
			
		||||
        if(!lazy || !(stack = lazy->Get<AnimationStack>())) {
 | 
			
		||||
            DOMWarning("failed to read AnimationStack object");
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
        animationStacksResolved.push_back(stack);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return animationStacksResolved;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
LazyObject* Document::GetObject(uint64_t id) const
 | 
			
		||||
{
 | 
			
		||||
    ObjectMap::const_iterator it = objects.find(id);
 | 
			
		||||
    return it == objects.end() ? nullptr : (*it).second;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define MAX_CLASSNAMES 6
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
std::vector<const Connection*> Document::GetConnectionsSequenced(uint64_t id, const ConnectionMap& conns) const
 | 
			
		||||
{
 | 
			
		||||
    std::vector<const Connection*> temp;
 | 
			
		||||
 | 
			
		||||
    const std::pair<ConnectionMap::const_iterator,ConnectionMap::const_iterator> range =
 | 
			
		||||
        conns.equal_range(id);
 | 
			
		||||
 | 
			
		||||
    temp.reserve(std::distance(range.first,range.second));
 | 
			
		||||
    for (ConnectionMap::const_iterator it = range.first; it != range.second; ++it) {
 | 
			
		||||
        temp.push_back((*it).second);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::sort(temp.begin(), temp.end(), std::mem_fn(&Connection::Compare));
 | 
			
		||||
 | 
			
		||||
    return temp; // NRVO should handle this
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
std::vector<const Connection*> Document::GetConnectionsSequenced(uint64_t id, bool is_src,
 | 
			
		||||
    const ConnectionMap& conns,
 | 
			
		||||
    const char* const* classnames,
 | 
			
		||||
    size_t count) const
 | 
			
		||||
 | 
			
		||||
{
 | 
			
		||||
    ai_assert(classnames);
 | 
			
		||||
    ai_assert( count != 0 );
 | 
			
		||||
    ai_assert( count <= MAX_CLASSNAMES);
 | 
			
		||||
 | 
			
		||||
    size_t lengths[MAX_CLASSNAMES];
 | 
			
		||||
 | 
			
		||||
    const size_t c = count;
 | 
			
		||||
    for (size_t i = 0; i < c; ++i) {
 | 
			
		||||
        lengths[ i ] = strlen(classnames[i]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::vector<const Connection*> temp;
 | 
			
		||||
    const std::pair<ConnectionMap::const_iterator,ConnectionMap::const_iterator> range =
 | 
			
		||||
        conns.equal_range(id);
 | 
			
		||||
 | 
			
		||||
    temp.reserve(std::distance(range.first,range.second));
 | 
			
		||||
    for (ConnectionMap::const_iterator it = range.first; it != range.second; ++it) {
 | 
			
		||||
        const Token& key = (is_src
 | 
			
		||||
            ? (*it).second->LazyDestinationObject()
 | 
			
		||||
            : (*it).second->LazySourceObject()
 | 
			
		||||
        ).GetElement().KeyToken();
 | 
			
		||||
 | 
			
		||||
        const char* obtype = key.begin();
 | 
			
		||||
 | 
			
		||||
        for (size_t i = 0; i < c; ++i) {
 | 
			
		||||
            ai_assert(classnames[i]);
 | 
			
		||||
            if(static_cast<size_t>(std::distance(key.begin(),key.end())) == lengths[i] && !strncmp(classnames[i],obtype,lengths[i])) {
 | 
			
		||||
                obtype = nullptr;
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if(obtype) {
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        temp.push_back((*it).second);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::sort(temp.begin(), temp.end(), std::mem_fn(&Connection::Compare));
 | 
			
		||||
    return temp; // NRVO should handle this
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
std::vector<const Connection*> Document::GetConnectionsBySourceSequenced(uint64_t source) const
 | 
			
		||||
{
 | 
			
		||||
    return GetConnectionsSequenced(source, ConnectionsBySource());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
std::vector<const Connection*> Document::GetConnectionsBySourceSequenced(uint64_t src, const char* classname) const
 | 
			
		||||
{
 | 
			
		||||
    const char* arr[] = {classname};
 | 
			
		||||
    return GetConnectionsBySourceSequenced(src, arr,1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
std::vector<const Connection*> Document::GetConnectionsBySourceSequenced(uint64_t source, 
 | 
			
		||||
        const char* const* classnames, size_t count) const
 | 
			
		||||
{
 | 
			
		||||
    return GetConnectionsSequenced(source, true, ConnectionsBySource(),classnames, count);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
std::vector<const Connection*> Document::GetConnectionsByDestinationSequenced(uint64_t dest,
 | 
			
		||||
        const char* classname) const
 | 
			
		||||
{
 | 
			
		||||
    const char* arr[] = {classname};
 | 
			
		||||
    return GetConnectionsByDestinationSequenced(dest, arr,1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
std::vector<const Connection*> Document::GetConnectionsByDestinationSequenced(uint64_t dest) const
 | 
			
		||||
{
 | 
			
		||||
    return GetConnectionsSequenced(dest, ConnectionsByDestination());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
std::vector<const Connection*> Document::GetConnectionsByDestinationSequenced(uint64_t dest,
 | 
			
		||||
    const char* const* classnames, size_t count) const
 | 
			
		||||
 | 
			
		||||
{
 | 
			
		||||
    return GetConnectionsSequenced(dest, false, ConnectionsByDestination(),classnames, count);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
Connection::Connection(uint64_t insertionOrder,  uint64_t src, uint64_t dest, const std::string& prop,
 | 
			
		||||
        const Document& doc)
 | 
			
		||||
 | 
			
		||||
: insertionOrder(insertionOrder)
 | 
			
		||||
, prop(prop)
 | 
			
		||||
, src(src)
 | 
			
		||||
, dest(dest)
 | 
			
		||||
, doc(doc)
 | 
			
		||||
{
 | 
			
		||||
    ai_assert(doc.Objects().find(src) != doc.Objects().end());
 | 
			
		||||
    // dest may be 0 (root node)
 | 
			
		||||
    ai_assert(!dest || doc.Objects().find(dest) != doc.Objects().end());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
Connection::~Connection()
 | 
			
		||||
{
 | 
			
		||||
    // empty
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
LazyObject& Connection::LazySourceObject() const
 | 
			
		||||
{
 | 
			
		||||
    LazyObject* const lazy = doc.GetObject(src);
 | 
			
		||||
    ai_assert(lazy);
 | 
			
		||||
    return *lazy;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
LazyObject& Connection::LazyDestinationObject() const
 | 
			
		||||
{
 | 
			
		||||
    LazyObject* const lazy = doc.GetObject(dest);
 | 
			
		||||
    ai_assert(lazy);
 | 
			
		||||
    return *lazy;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
const Object* Connection::SourceObject() const
 | 
			
		||||
{
 | 
			
		||||
    LazyObject* const lazy = doc.GetObject(src);
 | 
			
		||||
    ai_assert(lazy);
 | 
			
		||||
    return lazy->Get();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
const Object* Connection::DestinationObject() const
 | 
			
		||||
{
 | 
			
		||||
    LazyObject* const lazy = doc.GetObject(dest);
 | 
			
		||||
    ai_assert(lazy);
 | 
			
		||||
    return lazy->Get();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // !FBX
 | 
			
		||||
} // !Assimp
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										1180
									
								
								thirdparty/assimp/code/FBX/FBXDocument.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1180
									
								
								thirdparty/assimp/code/FBX/FBXDocument.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										135
									
								
								thirdparty/assimp/code/FBX/FBXDocumentUtil.cpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										135
									
								
								thirdparty/assimp/code/FBX/FBXDocumentUtil.cpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,135 @@
 | 
			
		||||
/*
 | 
			
		||||
Open Asset Import Library (assimp)
 | 
			
		||||
----------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
Copyright (c) 2006-2019, 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  FBXDocumentUtil.cpp
 | 
			
		||||
 *  @brief Implementation of the FBX DOM utility functions declared in FBXDocumentUtil.h
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef ASSIMP_BUILD_NO_FBX_IMPORTER
 | 
			
		||||
 | 
			
		||||
#include "FBXParser.h"
 | 
			
		||||
#include "FBXDocument.h"
 | 
			
		||||
#include "FBXUtil.h"
 | 
			
		||||
#include "FBXDocumentUtil.h"
 | 
			
		||||
#include "FBXProperties.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
namespace Assimp {
 | 
			
		||||
namespace FBX {
 | 
			
		||||
namespace Util {
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
// signal DOM construction error, this is always unrecoverable. Throws DeadlyImportError.
 | 
			
		||||
void DOMError(const std::string& message, const Token& token)
 | 
			
		||||
{
 | 
			
		||||
    throw DeadlyImportError(Util::AddTokenText("FBX-DOM",message,&token));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
void DOMError(const std::string& message, const Element* element /*= NULL*/)
 | 
			
		||||
{
 | 
			
		||||
    if(element) {
 | 
			
		||||
        DOMError(message,element->KeyToken());
 | 
			
		||||
    }
 | 
			
		||||
    throw DeadlyImportError("FBX-DOM " + message);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
// print warning, do return
 | 
			
		||||
void DOMWarning(const std::string& message, const Token& token)
 | 
			
		||||
{
 | 
			
		||||
    if(DefaultLogger::get()) {
 | 
			
		||||
        ASSIMP_LOG_WARN(Util::AddTokenText("FBX-DOM",message,&token));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
void DOMWarning(const std::string& message, const Element* element /*= NULL*/)
 | 
			
		||||
{
 | 
			
		||||
    if(element) {
 | 
			
		||||
        DOMWarning(message,element->KeyToken());
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    if(DefaultLogger::get()) {
 | 
			
		||||
        ASSIMP_LOG_WARN("FBX-DOM: " + message);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
// fetch a property table and the corresponding property template
 | 
			
		||||
std::shared_ptr<const PropertyTable> GetPropertyTable(const Document& doc,
 | 
			
		||||
    const std::string& templateName,
 | 
			
		||||
    const Element &element,
 | 
			
		||||
    const Scope& sc,
 | 
			
		||||
    bool no_warn /*= false*/)
 | 
			
		||||
{
 | 
			
		||||
    const Element* const Properties70 = sc["Properties70"];
 | 
			
		||||
    std::shared_ptr<const PropertyTable> templateProps = std::shared_ptr<const PropertyTable>(
 | 
			
		||||
        static_cast<const PropertyTable*>(NULL));
 | 
			
		||||
 | 
			
		||||
    if(templateName.length()) {
 | 
			
		||||
        PropertyTemplateMap::const_iterator it = doc.Templates().find(templateName);
 | 
			
		||||
        if(it != doc.Templates().end()) {
 | 
			
		||||
            templateProps = (*it).second;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(!Properties70 || !Properties70->Compound()) {
 | 
			
		||||
        if(!no_warn) {
 | 
			
		||||
            DOMWarning("property table (Properties70) not found",&element);
 | 
			
		||||
        }
 | 
			
		||||
        if(templateProps) {
 | 
			
		||||
            return templateProps;
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
            return std::make_shared<const PropertyTable>();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return std::make_shared<const PropertyTable>(*Properties70,templateProps);
 | 
			
		||||
}
 | 
			
		||||
} // !Util
 | 
			
		||||
} // !FBX
 | 
			
		||||
} // !Assimp
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										120
									
								
								thirdparty/assimp/code/FBX/FBXDocumentUtil.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										120
									
								
								thirdparty/assimp/code/FBX/FBXDocumentUtil.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,120 @@
 | 
			
		||||
/*
 | 
			
		||||
Open Asset Import Library (assimp)
 | 
			
		||||
----------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
Copyright (c) 2006-2012, 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  FBXDocumentUtil.h
 | 
			
		||||
 *  @brief FBX internal utilities used by the DOM reading code
 | 
			
		||||
 */
 | 
			
		||||
#ifndef INCLUDED_AI_FBX_DOCUMENT_UTIL_H
 | 
			
		||||
#define INCLUDED_AI_FBX_DOCUMENT_UTIL_H
 | 
			
		||||
 | 
			
		||||
#include <assimp/defs.h>
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <memory>
 | 
			
		||||
#include "FBXDocument.h"
 | 
			
		||||
 | 
			
		||||
struct Token;
 | 
			
		||||
struct Element;
 | 
			
		||||
 | 
			
		||||
namespace Assimp {
 | 
			
		||||
namespace FBX {
 | 
			
		||||
namespace Util {
 | 
			
		||||
 | 
			
		||||
/* DOM/Parse error reporting - does not return */
 | 
			
		||||
AI_WONT_RETURN void DOMError(const std::string& message, const Token& token) AI_WONT_RETURN_SUFFIX;
 | 
			
		||||
AI_WONT_RETURN void DOMError(const std::string& message, const Element* element = NULL) AI_WONT_RETURN_SUFFIX;
 | 
			
		||||
 | 
			
		||||
// does return
 | 
			
		||||
void DOMWarning(const std::string& message, const Token& token);
 | 
			
		||||
void DOMWarning(const std::string& message, const Element* element = NULL);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// fetch a property table and the corresponding property template
 | 
			
		||||
std::shared_ptr<const PropertyTable> GetPropertyTable(const Document& doc,
 | 
			
		||||
    const std::string& templateName,
 | 
			
		||||
    const Element &element,
 | 
			
		||||
    const Scope& sc,
 | 
			
		||||
    bool no_warn = false);
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
template <typename T>
 | 
			
		||||
inline
 | 
			
		||||
const T* ProcessSimpleConnection(const Connection& con,
 | 
			
		||||
    bool is_object_property_conn,
 | 
			
		||||
    const char* name,
 | 
			
		||||
    const Element& element,
 | 
			
		||||
    const char** propNameOut = nullptr)
 | 
			
		||||
{
 | 
			
		||||
    if (is_object_property_conn && !con.PropertyName().length()) {
 | 
			
		||||
        DOMWarning("expected incoming " + std::string(name) +
 | 
			
		||||
            " link to be an object-object connection, ignoring",
 | 
			
		||||
            &element
 | 
			
		||||
            );
 | 
			
		||||
        return nullptr;
 | 
			
		||||
    }
 | 
			
		||||
    else if (!is_object_property_conn && con.PropertyName().length()) {
 | 
			
		||||
        DOMWarning("expected incoming " + std::string(name) +
 | 
			
		||||
            " link to be an object-property connection, ignoring",
 | 
			
		||||
            &element
 | 
			
		||||
            );
 | 
			
		||||
        return nullptr;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(is_object_property_conn && propNameOut) {
 | 
			
		||||
        // note: this is ok, the return value of PropertyValue() is guaranteed to
 | 
			
		||||
        // remain valid and unchanged as long as the document exists.
 | 
			
		||||
        *propNameOut = con.PropertyName().c_str();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const Object* const ob = con.SourceObject();
 | 
			
		||||
    if(!ob) {
 | 
			
		||||
        DOMWarning("failed to read source object for incoming " + std::string(name) +
 | 
			
		||||
            " link, ignoring",
 | 
			
		||||
            &element);
 | 
			
		||||
        return nullptr;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return dynamic_cast<const T*>(ob);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} //!Util
 | 
			
		||||
} //!FBX
 | 
			
		||||
} //!Assimp
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										571
									
								
								thirdparty/assimp/code/FBX/FBXExportNode.cpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										571
									
								
								thirdparty/assimp/code/FBX/FBXExportNode.cpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,571 @@
 | 
			
		||||
/*
 | 
			
		||||
Open Asset Import Library (assimp)
 | 
			
		||||
----------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
Copyright (c) 2006-2019, 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.
 | 
			
		||||
 | 
			
		||||
----------------------------------------------------------------------
 | 
			
		||||
*/
 | 
			
		||||
#ifndef ASSIMP_BUILD_NO_EXPORT
 | 
			
		||||
#ifndef ASSIMP_BUILD_NO_FBX_EXPORTER
 | 
			
		||||
 | 
			
		||||
#include "FBXExportNode.h"
 | 
			
		||||
#include "FBXCommon.h"
 | 
			
		||||
 | 
			
		||||
#include <assimp/StreamWriter.h> // StreamWriterLE
 | 
			
		||||
#include <assimp/Exceptional.h> // DeadlyExportError
 | 
			
		||||
#include <assimp/ai_assert.h>
 | 
			
		||||
#include <assimp/StringUtils.h> // ai_snprintf
 | 
			
		||||
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <ostream>
 | 
			
		||||
#include <sstream> // ostringstream
 | 
			
		||||
#include <memory> // shared_ptr
 | 
			
		||||
 | 
			
		||||
namespace Assimp {
 | 
			
		||||
// AddP70<type> helpers... there's no usable pattern here,
 | 
			
		||||
// so all are defined as separate functions.
 | 
			
		||||
// Even "animatable" properties are often completely different
 | 
			
		||||
// from the standard (nonanimated) property definition,
 | 
			
		||||
// so they are specified with an 'A' suffix.
 | 
			
		||||
 | 
			
		||||
void FBX::Node::AddP70int(
 | 
			
		||||
    const std::string& name, int32_t value
 | 
			
		||||
) {
 | 
			
		||||
    FBX::Node n("P");
 | 
			
		||||
    n.AddProperties(name, "int", "Integer", "", value);
 | 
			
		||||
    AddChild(n);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void FBX::Node::AddP70bool(
 | 
			
		||||
    const std::string& name, bool value
 | 
			
		||||
) {
 | 
			
		||||
    FBX::Node n("P");
 | 
			
		||||
    n.AddProperties(name, "bool", "", "", int32_t(value));
 | 
			
		||||
    AddChild(n);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void FBX::Node::AddP70double(
 | 
			
		||||
    const std::string& name, double value
 | 
			
		||||
) {
 | 
			
		||||
    FBX::Node n("P");
 | 
			
		||||
    n.AddProperties(name, "double", "Number", "", value);
 | 
			
		||||
    AddChild(n);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void FBX::Node::AddP70numberA(
 | 
			
		||||
    const std::string& name, double value
 | 
			
		||||
) {
 | 
			
		||||
    FBX::Node n("P");
 | 
			
		||||
    n.AddProperties(name, "Number", "", "A", value);
 | 
			
		||||
    AddChild(n);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void FBX::Node::AddP70color(
 | 
			
		||||
    const std::string& name, double r, double g, double b
 | 
			
		||||
) {
 | 
			
		||||
    FBX::Node n("P");
 | 
			
		||||
    n.AddProperties(name, "ColorRGB", "Color", "", r, g, b);
 | 
			
		||||
    AddChild(n);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void FBX::Node::AddP70colorA(
 | 
			
		||||
    const std::string& name, double r, double g, double b
 | 
			
		||||
) {
 | 
			
		||||
    FBX::Node n("P");
 | 
			
		||||
    n.AddProperties(name, "Color", "", "A", r, g, b);
 | 
			
		||||
    AddChild(n);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void FBX::Node::AddP70vector(
 | 
			
		||||
    const std::string& name, double x, double y, double z
 | 
			
		||||
) {
 | 
			
		||||
    FBX::Node n("P");
 | 
			
		||||
    n.AddProperties(name, "Vector3D", "Vector", "", x, y, z);
 | 
			
		||||
    AddChild(n);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void FBX::Node::AddP70vectorA(
 | 
			
		||||
    const std::string& name, double x, double y, double z
 | 
			
		||||
) {
 | 
			
		||||
    FBX::Node n("P");
 | 
			
		||||
    n.AddProperties(name, "Vector", "", "A", x, y, z);
 | 
			
		||||
    AddChild(n);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void FBX::Node::AddP70string(
 | 
			
		||||
    const std::string& name, const std::string& value
 | 
			
		||||
) {
 | 
			
		||||
    FBX::Node n("P");
 | 
			
		||||
    n.AddProperties(name, "KString", "", "", value);
 | 
			
		||||
    AddChild(n);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void FBX::Node::AddP70enum(
 | 
			
		||||
    const std::string& name, int32_t value
 | 
			
		||||
) {
 | 
			
		||||
    FBX::Node n("P");
 | 
			
		||||
    n.AddProperties(name, "enum", "", "", value);
 | 
			
		||||
    AddChild(n);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void FBX::Node::AddP70time(
 | 
			
		||||
    const std::string& name, int64_t value
 | 
			
		||||
) {
 | 
			
		||||
    FBX::Node n("P");
 | 
			
		||||
    n.AddProperties(name, "KTime", "Time", "", value);
 | 
			
		||||
    AddChild(n);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// public member functions for writing nodes to stream
 | 
			
		||||
 | 
			
		||||
void FBX::Node::Dump(
 | 
			
		||||
    std::shared_ptr<Assimp::IOStream> outfile,
 | 
			
		||||
    bool binary, int indent
 | 
			
		||||
) {
 | 
			
		||||
    if (binary) {
 | 
			
		||||
        Assimp::StreamWriterLE outstream(outfile);
 | 
			
		||||
        DumpBinary(outstream);
 | 
			
		||||
    } else {
 | 
			
		||||
        std::ostringstream ss;
 | 
			
		||||
        DumpAscii(ss, indent);
 | 
			
		||||
        std::string s = ss.str();
 | 
			
		||||
        outfile->Write(s.c_str(), s.size(), 1);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void FBX::Node::Dump(
 | 
			
		||||
    Assimp::StreamWriterLE &outstream,
 | 
			
		||||
    bool binary, int indent
 | 
			
		||||
) {
 | 
			
		||||
    if (binary) {
 | 
			
		||||
        DumpBinary(outstream);
 | 
			
		||||
    } else {
 | 
			
		||||
        std::ostringstream ss;
 | 
			
		||||
        DumpAscii(ss, indent);
 | 
			
		||||
        outstream.PutString(ss.str());
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// public member functions for low-level writing
 | 
			
		||||
 | 
			
		||||
void FBX::Node::Begin(
 | 
			
		||||
    Assimp::StreamWriterLE &s,
 | 
			
		||||
    bool binary, int indent
 | 
			
		||||
) {
 | 
			
		||||
    if (binary) {
 | 
			
		||||
        BeginBinary(s);
 | 
			
		||||
    } else {
 | 
			
		||||
        // assume we're at the correct place to start already
 | 
			
		||||
        (void)indent;
 | 
			
		||||
        std::ostringstream ss;
 | 
			
		||||
        BeginAscii(ss, indent);
 | 
			
		||||
        s.PutString(ss.str());
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void FBX::Node::DumpProperties(
 | 
			
		||||
    Assimp::StreamWriterLE& s,
 | 
			
		||||
    bool binary, int indent
 | 
			
		||||
) {
 | 
			
		||||
    if (binary) {
 | 
			
		||||
        DumpPropertiesBinary(s);
 | 
			
		||||
    } else {
 | 
			
		||||
        std::ostringstream ss;
 | 
			
		||||
        DumpPropertiesAscii(ss, indent);
 | 
			
		||||
        s.PutString(ss.str());
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void FBX::Node::EndProperties(
 | 
			
		||||
    Assimp::StreamWriterLE &s,
 | 
			
		||||
    bool binary, int indent
 | 
			
		||||
) {
 | 
			
		||||
    EndProperties(s, binary, indent, properties.size());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void FBX::Node::EndProperties(
 | 
			
		||||
    Assimp::StreamWriterLE &s,
 | 
			
		||||
    bool binary, int indent,
 | 
			
		||||
    size_t num_properties
 | 
			
		||||
) {
 | 
			
		||||
    if (binary) {
 | 
			
		||||
        EndPropertiesBinary(s, num_properties);
 | 
			
		||||
    } else {
 | 
			
		||||
        // nothing to do
 | 
			
		||||
        (void)indent;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void FBX::Node::BeginChildren(
 | 
			
		||||
    Assimp::StreamWriterLE &s,
 | 
			
		||||
    bool binary, int indent
 | 
			
		||||
) {
 | 
			
		||||
    if (binary) {
 | 
			
		||||
        // nothing to do
 | 
			
		||||
    } else {
 | 
			
		||||
        std::ostringstream ss;
 | 
			
		||||
        BeginChildrenAscii(ss, indent);
 | 
			
		||||
        s.PutString(ss.str());
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void FBX::Node::DumpChildren(
 | 
			
		||||
    Assimp::StreamWriterLE& s,
 | 
			
		||||
    bool binary, int indent
 | 
			
		||||
) {
 | 
			
		||||
    if (binary) {
 | 
			
		||||
        DumpChildrenBinary(s);
 | 
			
		||||
    } else {
 | 
			
		||||
        std::ostringstream ss;
 | 
			
		||||
        DumpChildrenAscii(ss, indent);
 | 
			
		||||
        if (ss.tellp() > 0)
 | 
			
		||||
            s.PutString(ss.str());
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void FBX::Node::End(
 | 
			
		||||
    Assimp::StreamWriterLE &s,
 | 
			
		||||
    bool binary, int indent,
 | 
			
		||||
    bool has_children
 | 
			
		||||
) {
 | 
			
		||||
    if (binary) {
 | 
			
		||||
        EndBinary(s, has_children);
 | 
			
		||||
    } else {
 | 
			
		||||
        std::ostringstream ss;
 | 
			
		||||
        EndAscii(ss, indent, has_children);
 | 
			
		||||
        if (ss.tellp() > 0)
 | 
			
		||||
            s.PutString(ss.str());
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// public member functions for writing to binary fbx
 | 
			
		||||
 | 
			
		||||
void FBX::Node::DumpBinary(Assimp::StreamWriterLE &s)
 | 
			
		||||
{
 | 
			
		||||
    // write header section (with placeholders for some things)
 | 
			
		||||
    BeginBinary(s);
 | 
			
		||||
 | 
			
		||||
    // write properties
 | 
			
		||||
    DumpPropertiesBinary(s);
 | 
			
		||||
 | 
			
		||||
    // go back and fill in property related placeholders
 | 
			
		||||
    EndPropertiesBinary(s, properties.size());
 | 
			
		||||
 | 
			
		||||
    // write children
 | 
			
		||||
    DumpChildrenBinary(s);
 | 
			
		||||
 | 
			
		||||
    // finish, filling in end offset placeholder
 | 
			
		||||
    EndBinary(s, force_has_children || !children.empty());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// public member functions for writing to ascii fbx
 | 
			
		||||
 | 
			
		||||
void FBX::Node::DumpAscii(std::ostream &s, int indent)
 | 
			
		||||
{
 | 
			
		||||
    // write name
 | 
			
		||||
    BeginAscii(s, indent);
 | 
			
		||||
 | 
			
		||||
    // write properties
 | 
			
		||||
    DumpPropertiesAscii(s, indent);
 | 
			
		||||
 | 
			
		||||
    if (force_has_children || !children.empty()) {
 | 
			
		||||
        // begin children (with a '{')
 | 
			
		||||
        BeginChildrenAscii(s, indent + 1);
 | 
			
		||||
        // write children
 | 
			
		||||
        DumpChildrenAscii(s, indent + 1);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // finish (also closing the children bracket '}')
 | 
			
		||||
    EndAscii(s, indent, force_has_children || !children.empty());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// private member functions for low-level writing to fbx
 | 
			
		||||
 | 
			
		||||
void FBX::Node::BeginBinary(Assimp::StreamWriterLE &s)
 | 
			
		||||
{
 | 
			
		||||
    // remember start pos so we can come back and write the end pos
 | 
			
		||||
    this->start_pos = s.Tell();
 | 
			
		||||
 | 
			
		||||
    // placeholders for end pos and property section info
 | 
			
		||||
    s.PutU4(0); // end pos
 | 
			
		||||
    s.PutU4(0); // number of properties
 | 
			
		||||
    s.PutU4(0); // total property section length
 | 
			
		||||
 | 
			
		||||
    // node name
 | 
			
		||||
    s.PutU1(uint8_t(name.size())); // length of node name
 | 
			
		||||
    s.PutString(name); // node name as raw bytes
 | 
			
		||||
 | 
			
		||||
    // property data comes after here
 | 
			
		||||
    this->property_start = s.Tell();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void FBX::Node::DumpPropertiesBinary(Assimp::StreamWriterLE& s)
 | 
			
		||||
{
 | 
			
		||||
    for (auto &p : properties) {
 | 
			
		||||
        p.DumpBinary(s);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void FBX::Node::EndPropertiesBinary(
 | 
			
		||||
    Assimp::StreamWriterLE &s,
 | 
			
		||||
    size_t num_properties
 | 
			
		||||
) {
 | 
			
		||||
    if (num_properties == 0) { return; }
 | 
			
		||||
    size_t pos = s.Tell();
 | 
			
		||||
    ai_assert(pos > property_start);
 | 
			
		||||
    size_t property_section_size = pos - property_start;
 | 
			
		||||
    s.Seek(start_pos + 4);
 | 
			
		||||
    s.PutU4(uint32_t(num_properties));
 | 
			
		||||
    s.PutU4(uint32_t(property_section_size));
 | 
			
		||||
    s.Seek(pos);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void FBX::Node::DumpChildrenBinary(Assimp::StreamWriterLE& s)
 | 
			
		||||
{
 | 
			
		||||
    for (FBX::Node& child : children) {
 | 
			
		||||
        child.DumpBinary(s);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void FBX::Node::EndBinary(
 | 
			
		||||
    Assimp::StreamWriterLE &s,
 | 
			
		||||
    bool has_children
 | 
			
		||||
) {
 | 
			
		||||
    // if there were children, add a null record
 | 
			
		||||
    if (has_children) { s.PutString(Assimp::FBX::NULL_RECORD); }
 | 
			
		||||
 | 
			
		||||
    // now go back and write initial pos
 | 
			
		||||
    this->end_pos = s.Tell();
 | 
			
		||||
    s.Seek(start_pos);
 | 
			
		||||
    s.PutU4(uint32_t(end_pos));
 | 
			
		||||
    s.Seek(end_pos);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void FBX::Node::BeginAscii(std::ostream& s, int indent)
 | 
			
		||||
{
 | 
			
		||||
    s << '\n';
 | 
			
		||||
    for (int i = 0; i < indent; ++i) { s << '\t'; }
 | 
			
		||||
    s << name << ": ";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void FBX::Node::DumpPropertiesAscii(std::ostream &s, int indent)
 | 
			
		||||
{
 | 
			
		||||
    for (size_t i = 0; i < properties.size(); ++i) {
 | 
			
		||||
        if (i > 0) { s << ", "; }
 | 
			
		||||
        properties[i].DumpAscii(s, indent);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void FBX::Node::BeginChildrenAscii(std::ostream& s, int indent)
 | 
			
		||||
{
 | 
			
		||||
    // only call this if there are actually children
 | 
			
		||||
    s << " {";
 | 
			
		||||
    (void)indent;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void FBX::Node::DumpChildrenAscii(std::ostream& s, int indent)
 | 
			
		||||
{
 | 
			
		||||
    // children will need a lot of padding and corralling
 | 
			
		||||
    if (children.size() || force_has_children) {
 | 
			
		||||
        for (size_t i = 0; i < children.size(); ++i) {
 | 
			
		||||
            // no compression in ascii files, so skip this node if it exists
 | 
			
		||||
            if (children[i].name == "EncryptionType") { continue; }
 | 
			
		||||
            // the child can dump itself
 | 
			
		||||
            children[i].DumpAscii(s, indent);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void FBX::Node::EndAscii(std::ostream& s, int indent, bool has_children)
 | 
			
		||||
{
 | 
			
		||||
    if (!has_children) { return; } // nothing to do
 | 
			
		||||
    s << '\n';
 | 
			
		||||
    for (int i = 0; i < indent; ++i) { s << '\t'; }
 | 
			
		||||
    s << "}";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// private helpers for static member functions
 | 
			
		||||
 | 
			
		||||
// ascii property node from vector of doubles
 | 
			
		||||
void FBX::Node::WritePropertyNodeAscii(
 | 
			
		||||
    const std::string& name,
 | 
			
		||||
    const std::vector<double>& v,
 | 
			
		||||
    Assimp::StreamWriterLE& s,
 | 
			
		||||
    int indent
 | 
			
		||||
){
 | 
			
		||||
    char buffer[32];
 | 
			
		||||
    FBX::Node node(name);
 | 
			
		||||
    node.Begin(s, false, indent);
 | 
			
		||||
    std::string vsize = to_string(v.size());
 | 
			
		||||
    // *<size> {
 | 
			
		||||
    s.PutChar('*'); s.PutString(vsize); s.PutString(" {\n");
 | 
			
		||||
    // indent + 1
 | 
			
		||||
    for (int i = 0; i < indent + 1; ++i) { s.PutChar('\t'); }
 | 
			
		||||
    // a: value,value,value,...
 | 
			
		||||
    s.PutString("a: ");
 | 
			
		||||
    int count = 0;
 | 
			
		||||
    for (size_t i = 0; i < v.size(); ++i) {
 | 
			
		||||
        if (i > 0) { s.PutChar(','); }
 | 
			
		||||
        int len = ai_snprintf(buffer, sizeof(buffer), "%f", v[i]);
 | 
			
		||||
        count += len;
 | 
			
		||||
        if (count > 2048) { s.PutChar('\n'); count = 0; }
 | 
			
		||||
        if (len < 0 || len > 31) {
 | 
			
		||||
            // this should never happen
 | 
			
		||||
            throw DeadlyExportError("failed to convert double to string");
 | 
			
		||||
        }
 | 
			
		||||
        for (int j = 0; j < len; ++j) { s.PutChar(buffer[j]); }
 | 
			
		||||
    }
 | 
			
		||||
    // }
 | 
			
		||||
    s.PutChar('\n');
 | 
			
		||||
    for (int i = 0; i < indent; ++i) { s.PutChar('\t'); }
 | 
			
		||||
    s.PutChar('}'); s.PutChar(' ');
 | 
			
		||||
    node.End(s, false, indent, false);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ascii property node from vector of int32_t
 | 
			
		||||
void FBX::Node::WritePropertyNodeAscii(
 | 
			
		||||
    const std::string& name,
 | 
			
		||||
    const std::vector<int32_t>& v,
 | 
			
		||||
    Assimp::StreamWriterLE& s,
 | 
			
		||||
    int indent
 | 
			
		||||
){
 | 
			
		||||
    char buffer[32];
 | 
			
		||||
    FBX::Node node(name);
 | 
			
		||||
    node.Begin(s, false, indent);
 | 
			
		||||
    std::string vsize = to_string(v.size());
 | 
			
		||||
    // *<size> {
 | 
			
		||||
    s.PutChar('*'); s.PutString(vsize); s.PutString(" {\n");
 | 
			
		||||
    // indent + 1
 | 
			
		||||
    for (int i = 0; i < indent + 1; ++i) { s.PutChar('\t'); }
 | 
			
		||||
    // a: value,value,value,...
 | 
			
		||||
    s.PutString("a: ");
 | 
			
		||||
    int count = 0;
 | 
			
		||||
    for (size_t i = 0; i < v.size(); ++i) {
 | 
			
		||||
        if (i > 0) { s.PutChar(','); }
 | 
			
		||||
        int len = ai_snprintf(buffer, sizeof(buffer), "%d", v[i]);
 | 
			
		||||
        count += len;
 | 
			
		||||
        if (count > 2048) { s.PutChar('\n'); count = 0; }
 | 
			
		||||
        if (len < 0 || len > 31) {
 | 
			
		||||
            // this should never happen
 | 
			
		||||
            throw DeadlyExportError("failed to convert double to string");
 | 
			
		||||
        }
 | 
			
		||||
        for (int j = 0; j < len; ++j) { s.PutChar(buffer[j]); }
 | 
			
		||||
    }
 | 
			
		||||
    // }
 | 
			
		||||
    s.PutChar('\n');
 | 
			
		||||
    for (int i = 0; i < indent; ++i) { s.PutChar('\t'); }
 | 
			
		||||
    s.PutChar('}'); s.PutChar(' ');
 | 
			
		||||
    node.End(s, false, indent, false);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// binary property node from vector of doubles
 | 
			
		||||
// TODO: optional zip compression!
 | 
			
		||||
void FBX::Node::WritePropertyNodeBinary(
 | 
			
		||||
    const std::string& name,
 | 
			
		||||
    const std::vector<double>& v,
 | 
			
		||||
    Assimp::StreamWriterLE& s
 | 
			
		||||
){
 | 
			
		||||
    FBX::Node node(name);
 | 
			
		||||
    node.BeginBinary(s);
 | 
			
		||||
    s.PutU1('d');
 | 
			
		||||
    s.PutU4(uint32_t(v.size())); // number of elements
 | 
			
		||||
    s.PutU4(0); // no encoding (1 would be zip-compressed)
 | 
			
		||||
    s.PutU4(uint32_t(v.size()) * 8); // data size
 | 
			
		||||
    for (auto it = v.begin(); it != v.end(); ++it) { s.PutF8(*it); }
 | 
			
		||||
    node.EndPropertiesBinary(s, 1);
 | 
			
		||||
    node.EndBinary(s, false);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// binary property node from vector of int32_t
 | 
			
		||||
// TODO: optional zip compression!
 | 
			
		||||
void FBX::Node::WritePropertyNodeBinary(
 | 
			
		||||
    const std::string& name,
 | 
			
		||||
    const std::vector<int32_t>& v,
 | 
			
		||||
    Assimp::StreamWriterLE& s
 | 
			
		||||
){
 | 
			
		||||
    FBX::Node node(name);
 | 
			
		||||
    node.BeginBinary(s);
 | 
			
		||||
    s.PutU1('i');
 | 
			
		||||
    s.PutU4(uint32_t(v.size())); // number of elements
 | 
			
		||||
    s.PutU4(0); // no encoding (1 would be zip-compressed)
 | 
			
		||||
    s.PutU4(uint32_t(v.size()) * 4); // data size
 | 
			
		||||
    for (auto it = v.begin(); it != v.end(); ++it) { s.PutI4(*it); }
 | 
			
		||||
    node.EndPropertiesBinary(s, 1);
 | 
			
		||||
    node.EndBinary(s, false);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// public static member functions
 | 
			
		||||
 | 
			
		||||
// convenience function to create and write a property node,
 | 
			
		||||
// holding a single property which is an array of values.
 | 
			
		||||
// does not copy the data, so is efficient for large arrays.
 | 
			
		||||
void FBX::Node::WritePropertyNode(
 | 
			
		||||
    const std::string& name,
 | 
			
		||||
    const std::vector<double>& v,
 | 
			
		||||
    Assimp::StreamWriterLE& s,
 | 
			
		||||
    bool binary, int indent
 | 
			
		||||
){
 | 
			
		||||
    if (binary) {
 | 
			
		||||
        FBX::Node::WritePropertyNodeBinary(name, v, s);
 | 
			
		||||
    } else {
 | 
			
		||||
        FBX::Node::WritePropertyNodeAscii(name, v, s, indent);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// convenience function to create and write a property node,
 | 
			
		||||
// holding a single property which is an array of values.
 | 
			
		||||
// does not copy the data, so is efficient for large arrays.
 | 
			
		||||
void FBX::Node::WritePropertyNode(
 | 
			
		||||
    const std::string& name,
 | 
			
		||||
    const std::vector<int32_t>& v,
 | 
			
		||||
    Assimp::StreamWriterLE& s,
 | 
			
		||||
    bool binary, int indent
 | 
			
		||||
){
 | 
			
		||||
    if (binary) {
 | 
			
		||||
        FBX::Node::WritePropertyNodeBinary(name, v, s);
 | 
			
		||||
    } else {
 | 
			
		||||
        FBX::Node::WritePropertyNodeAscii(name, v, s, indent);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
#endif // ASSIMP_BUILD_NO_FBX_EXPORTER
 | 
			
		||||
#endif // ASSIMP_BUILD_NO_EXPORT
 | 
			
		||||
							
								
								
									
										271
									
								
								thirdparty/assimp/code/FBX/FBXExportNode.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										271
									
								
								thirdparty/assimp/code/FBX/FBXExportNode.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,271 @@
 | 
			
		||||
/*
 | 
			
		||||
Open Asset Import Library (assimp)
 | 
			
		||||
----------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
Copyright (c) 2006-2019, 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 FBXExportNode.h
 | 
			
		||||
* Declares the FBX::Node helper class for fbx export.
 | 
			
		||||
*/
 | 
			
		||||
#ifndef AI_FBXEXPORTNODE_H_INC
 | 
			
		||||
#define AI_FBXEXPORTNODE_H_INC
 | 
			
		||||
 | 
			
		||||
#ifndef ASSIMP_BUILD_NO_FBX_EXPORTER
 | 
			
		||||
 | 
			
		||||
#include "FBXExportProperty.h"
 | 
			
		||||
 | 
			
		||||
#include <assimp/StreamWriter.h> // StreamWriterLE
 | 
			
		||||
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <vector>
 | 
			
		||||
 | 
			
		||||
namespace Assimp {
 | 
			
		||||
namespace FBX {
 | 
			
		||||
    class Node;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class FBX::Node {
 | 
			
		||||
public: 
 | 
			
		||||
    // TODO: accessors
 | 
			
		||||
    std::string name; // node name
 | 
			
		||||
    std::vector<FBX::FBXExportProperty> properties; // node properties
 | 
			
		||||
    std::vector<FBX::Node> children; // child nodes
 | 
			
		||||
 | 
			
		||||
    // some nodes always pretend they have children...
 | 
			
		||||
    bool force_has_children = false;
 | 
			
		||||
 | 
			
		||||
public: // constructors
 | 
			
		||||
    /// The default class constructor.
 | 
			
		||||
    Node() = default;
 | 
			
		||||
 | 
			
		||||
    /// The class constructor with the name.
 | 
			
		||||
    Node(const std::string& n)
 | 
			
		||||
    : name(n)
 | 
			
		||||
    , properties()
 | 
			
		||||
    , children()
 | 
			
		||||
    , force_has_children( false ) {
 | 
			
		||||
        // empty
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // convenience template to construct with properties directly
 | 
			
		||||
    template <typename... More>
 | 
			
		||||
    Node(const std::string& n, const More... more)
 | 
			
		||||
    : name(n)
 | 
			
		||||
    , properties()
 | 
			
		||||
    , children()
 | 
			
		||||
    , force_has_children(false) {
 | 
			
		||||
        AddProperties(more...);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
public: // functions to add properties or children
 | 
			
		||||
    // add a single property to the node
 | 
			
		||||
    template <typename T>
 | 
			
		||||
    void AddProperty(T value) {
 | 
			
		||||
        properties.emplace_back(value);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // convenience function to add multiple properties at once
 | 
			
		||||
    template <typename T, typename... More>
 | 
			
		||||
    void AddProperties(T value, More... more) {
 | 
			
		||||
        properties.emplace_back(value);
 | 
			
		||||
        AddProperties(more...);
 | 
			
		||||
    }
 | 
			
		||||
    void AddProperties() {}
 | 
			
		||||
 | 
			
		||||
    // add a child node directly
 | 
			
		||||
    void AddChild(const Node& node) { children.push_back(node); }
 | 
			
		||||
 | 
			
		||||
    // convenience function to add a child node with a single property
 | 
			
		||||
    template <typename... More>
 | 
			
		||||
    void AddChild(
 | 
			
		||||
        const std::string& name,
 | 
			
		||||
        More... more
 | 
			
		||||
    ) {
 | 
			
		||||
        FBX::Node c(name);
 | 
			
		||||
        c.AddProperties(more...);
 | 
			
		||||
        children.push_back(c);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
public: // support specifically for dealing with Properties70 nodes
 | 
			
		||||
 | 
			
		||||
    // it really is simpler to make these all separate functions.
 | 
			
		||||
    // the versions with 'A' suffixes are for animatable properties.
 | 
			
		||||
    // those often follow a completely different format internally in FBX.
 | 
			
		||||
    void AddP70int(const std::string& name, int32_t value);
 | 
			
		||||
    void AddP70bool(const std::string& name, bool value);
 | 
			
		||||
    void AddP70double(const std::string& name, double value);
 | 
			
		||||
    void AddP70numberA(const std::string& name, double value);
 | 
			
		||||
    void AddP70color(const std::string& name, double r, double g, double b);
 | 
			
		||||
    void AddP70colorA(const std::string& name, double r, double g, double b);
 | 
			
		||||
    void AddP70vector(const std::string& name, double x, double y, double z);
 | 
			
		||||
    void AddP70vectorA(const std::string& name, double x, double y, double z);
 | 
			
		||||
    void AddP70string(const std::string& name, const std::string& value);
 | 
			
		||||
    void AddP70enum(const std::string& name, int32_t value);
 | 
			
		||||
    void AddP70time(const std::string& name, int64_t value);
 | 
			
		||||
 | 
			
		||||
    // template for custom P70 nodes.
 | 
			
		||||
    // anything that doesn't fit in the above can be created manually.
 | 
			
		||||
    template <typename... More>
 | 
			
		||||
    void AddP70(
 | 
			
		||||
        const std::string& name,
 | 
			
		||||
        const std::string& type,
 | 
			
		||||
        const std::string& type2,
 | 
			
		||||
        const std::string& flags,
 | 
			
		||||
        More... more
 | 
			
		||||
    ) {
 | 
			
		||||
        Node n("P");
 | 
			
		||||
        n.AddProperties(name, type, type2, flags, more...);
 | 
			
		||||
        AddChild(n);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
public: // member functions for writing data to a file or stream
 | 
			
		||||
 | 
			
		||||
    // write the full node to the given file or stream
 | 
			
		||||
    void Dump(
 | 
			
		||||
        std::shared_ptr<Assimp::IOStream> outfile,
 | 
			
		||||
        bool binary, int indent
 | 
			
		||||
    );
 | 
			
		||||
    void Dump(Assimp::StreamWriterLE &s, bool binary, int indent);
 | 
			
		||||
 | 
			
		||||
    // these other functions are for writing data piece by piece.
 | 
			
		||||
    // they must be used carefully.
 | 
			
		||||
    // for usage examples see FBXExporter.cpp.
 | 
			
		||||
    void Begin(Assimp::StreamWriterLE &s, bool binary, int indent);
 | 
			
		||||
    void DumpProperties(Assimp::StreamWriterLE& s, bool binary, int indent);
 | 
			
		||||
    void EndProperties(Assimp::StreamWriterLE &s, bool binary, int indent);
 | 
			
		||||
    void EndProperties(
 | 
			
		||||
        Assimp::StreamWriterLE &s, bool binary, int indent,
 | 
			
		||||
        size_t num_properties
 | 
			
		||||
    );
 | 
			
		||||
    void BeginChildren(Assimp::StreamWriterLE &s, bool binary, int indent);
 | 
			
		||||
    void DumpChildren(Assimp::StreamWriterLE& s, bool binary, int indent);
 | 
			
		||||
    void End(
 | 
			
		||||
        Assimp::StreamWriterLE &s, bool binary, int indent,
 | 
			
		||||
        bool has_children
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
private: // internal functions used for writing
 | 
			
		||||
 | 
			
		||||
    void DumpBinary(Assimp::StreamWriterLE &s);
 | 
			
		||||
    void DumpAscii(Assimp::StreamWriterLE &s, int indent);
 | 
			
		||||
    void DumpAscii(std::ostream &s, int indent);
 | 
			
		||||
 | 
			
		||||
    void BeginBinary(Assimp::StreamWriterLE &s);
 | 
			
		||||
    void DumpPropertiesBinary(Assimp::StreamWriterLE& s);
 | 
			
		||||
    void EndPropertiesBinary(Assimp::StreamWriterLE &s);
 | 
			
		||||
    void EndPropertiesBinary(Assimp::StreamWriterLE &s, size_t num_properties);
 | 
			
		||||
    void DumpChildrenBinary(Assimp::StreamWriterLE& s);
 | 
			
		||||
    void EndBinary(Assimp::StreamWriterLE &s, bool has_children);
 | 
			
		||||
 | 
			
		||||
    void BeginAscii(std::ostream &s, int indent);
 | 
			
		||||
    void DumpPropertiesAscii(std::ostream &s, int indent);
 | 
			
		||||
    void BeginChildrenAscii(std::ostream &s, int indent);
 | 
			
		||||
    void DumpChildrenAscii(std::ostream &s, int indent);
 | 
			
		||||
    void EndAscii(std::ostream &s, int indent, bool has_children);
 | 
			
		||||
 | 
			
		||||
private: // data used for binary dumps
 | 
			
		||||
    size_t start_pos; // starting position in stream
 | 
			
		||||
    size_t end_pos; // ending position in stream
 | 
			
		||||
    size_t property_start; // starting position of property section
 | 
			
		||||
 | 
			
		||||
public: // static member functions
 | 
			
		||||
 | 
			
		||||
    // convenience function to create a node with a single property,
 | 
			
		||||
    // and write it to the stream.
 | 
			
		||||
    template <typename T>
 | 
			
		||||
    static void WritePropertyNode(
 | 
			
		||||
        const std::string& name,
 | 
			
		||||
        const T value,
 | 
			
		||||
        Assimp::StreamWriterLE& s,
 | 
			
		||||
        bool binary, int indent
 | 
			
		||||
    ) {
 | 
			
		||||
        FBX::FBXExportProperty p(value);
 | 
			
		||||
        FBX::Node node(name, p);
 | 
			
		||||
        node.Dump(s, binary, indent);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // convenience function to create and write a property node,
 | 
			
		||||
    // holding a single property which is an array of values.
 | 
			
		||||
    // does not copy the data, so is efficient for large arrays.
 | 
			
		||||
    static void WritePropertyNode(
 | 
			
		||||
        const std::string& name,
 | 
			
		||||
        const std::vector<double>& v,
 | 
			
		||||
        Assimp::StreamWriterLE& s,
 | 
			
		||||
        bool binary, int indent
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    // convenience function to create and write a property node,
 | 
			
		||||
    // holding a single property which is an array of values.
 | 
			
		||||
    // does not copy the data, so is efficient for large arrays.
 | 
			
		||||
    static void WritePropertyNode(
 | 
			
		||||
        const std::string& name,
 | 
			
		||||
        const std::vector<int32_t>& v,
 | 
			
		||||
        Assimp::StreamWriterLE& s,
 | 
			
		||||
        bool binary, int indent
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
private: // static helper functions
 | 
			
		||||
    static void WritePropertyNodeAscii(
 | 
			
		||||
        const std::string& name,
 | 
			
		||||
        const std::vector<double>& v,
 | 
			
		||||
        Assimp::StreamWriterLE& s,
 | 
			
		||||
        int indent
 | 
			
		||||
    );
 | 
			
		||||
    static void WritePropertyNodeAscii(
 | 
			
		||||
        const std::string& name,
 | 
			
		||||
        const std::vector<int32_t>& v,
 | 
			
		||||
        Assimp::StreamWriterLE& s,
 | 
			
		||||
        int indent
 | 
			
		||||
    );
 | 
			
		||||
    static void WritePropertyNodeBinary(
 | 
			
		||||
        const std::string& name,
 | 
			
		||||
        const std::vector<double>& v,
 | 
			
		||||
        Assimp::StreamWriterLE& s
 | 
			
		||||
    );
 | 
			
		||||
    static void WritePropertyNodeBinary(
 | 
			
		||||
        const std::string& name,
 | 
			
		||||
        const std::vector<int32_t>& v,
 | 
			
		||||
        Assimp::StreamWriterLE& s
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif // ASSIMP_BUILD_NO_FBX_EXPORTER
 | 
			
		||||
 | 
			
		||||
#endif // AI_FBXEXPORTNODE_H_INC
 | 
			
		||||
							
								
								
									
										385
									
								
								thirdparty/assimp/code/FBX/FBXExportProperty.cpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										385
									
								
								thirdparty/assimp/code/FBX/FBXExportProperty.cpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,385 @@
 | 
			
		||||
/*
 | 
			
		||||
Open Asset Import Library (assimp)
 | 
			
		||||
----------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
Copyright (c) 2006-2019, 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.
 | 
			
		||||
 | 
			
		||||
----------------------------------------------------------------------
 | 
			
		||||
*/
 | 
			
		||||
#ifndef ASSIMP_BUILD_NO_EXPORT
 | 
			
		||||
#ifndef ASSIMP_BUILD_NO_FBX_EXPORTER
 | 
			
		||||
 | 
			
		||||
#include "FBXExportProperty.h"
 | 
			
		||||
 | 
			
		||||
#include <assimp/StreamWriter.h> // StreamWriterLE
 | 
			
		||||
#include <assimp/Exceptional.h> // DeadlyExportError
 | 
			
		||||
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <vector>
 | 
			
		||||
#include <ostream>
 | 
			
		||||
#include <locale>
 | 
			
		||||
#include <sstream> // ostringstream
 | 
			
		||||
 | 
			
		||||
namespace Assimp {
 | 
			
		||||
namespace FBX {
 | 
			
		||||
 | 
			
		||||
// constructors for single element properties
 | 
			
		||||
 | 
			
		||||
FBXExportProperty::FBXExportProperty(bool v)
 | 
			
		||||
: type('C')
 | 
			
		||||
, data(1, uint8_t(v)) {}
 | 
			
		||||
 | 
			
		||||
FBXExportProperty::FBXExportProperty(int16_t v)
 | 
			
		||||
: type('Y')
 | 
			
		||||
, data(2) {
 | 
			
		||||
    uint8_t* d = data.data();
 | 
			
		||||
    (reinterpret_cast<int16_t*>(d))[0] = v;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
FBXExportProperty::FBXExportProperty(int32_t v)
 | 
			
		||||
: type('I')
 | 
			
		||||
, data(4) {
 | 
			
		||||
    uint8_t* d = data.data();
 | 
			
		||||
    (reinterpret_cast<int32_t*>(d))[0] = v;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
FBXExportProperty::FBXExportProperty(float v)
 | 
			
		||||
: type('F')
 | 
			
		||||
, data(4) {
 | 
			
		||||
    uint8_t* d = data.data();
 | 
			
		||||
    (reinterpret_cast<float*>(d))[0] = v;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
FBXExportProperty::FBXExportProperty(double v)
 | 
			
		||||
: type('D')
 | 
			
		||||
, data(8) {
 | 
			
		||||
    uint8_t* d = data.data();
 | 
			
		||||
    (reinterpret_cast<double*>(d))[0] = v;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
FBXExportProperty::FBXExportProperty(int64_t v)
 | 
			
		||||
: type('L')
 | 
			
		||||
, data(8) {
 | 
			
		||||
    uint8_t* d = data.data();
 | 
			
		||||
    (reinterpret_cast<int64_t*>(d))[0] = v;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// constructors for array-type properties
 | 
			
		||||
 | 
			
		||||
FBXExportProperty::FBXExportProperty(const char* c, bool raw)
 | 
			
		||||
: FBXExportProperty(std::string(c), raw) {
 | 
			
		||||
    // empty
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// strings can either be saved as "raw" (R) data, or "string" (S) data
 | 
			
		||||
FBXExportProperty::FBXExportProperty(const std::string& s, bool raw)
 | 
			
		||||
: type(raw ? 'R' : 'S')
 | 
			
		||||
, data(s.size()) {
 | 
			
		||||
    for (size_t i = 0; i < s.size(); ++i) {
 | 
			
		||||
        data[i] = uint8_t(s[i]);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
FBXExportProperty::FBXExportProperty(const std::vector<uint8_t>& r)
 | 
			
		||||
: type('R')
 | 
			
		||||
, data(r) {
 | 
			
		||||
    // empty
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
FBXExportProperty::FBXExportProperty(const std::vector<int32_t>& va)
 | 
			
		||||
: type('i')
 | 
			
		||||
, data(4 * va.size() ) {
 | 
			
		||||
    int32_t* d = reinterpret_cast<int32_t*>(data.data());
 | 
			
		||||
    for (size_t i = 0; i < va.size(); ++i) {
 | 
			
		||||
        d[i] = va[i];
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
FBXExportProperty::FBXExportProperty(const std::vector<int64_t>& va)
 | 
			
		||||
: type('l')
 | 
			
		||||
, data(8 * va.size()) {
 | 
			
		||||
    int64_t* d = reinterpret_cast<int64_t*>(data.data());
 | 
			
		||||
    for (size_t i = 0; i < va.size(); ++i) {
 | 
			
		||||
        d[i] = va[i];
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
FBXExportProperty::FBXExportProperty(const std::vector<float>& va)
 | 
			
		||||
: type('f')
 | 
			
		||||
, data(4 * va.size()) {
 | 
			
		||||
    float* d = reinterpret_cast<float*>(data.data());
 | 
			
		||||
    for (size_t i = 0; i < va.size(); ++i) {
 | 
			
		||||
        d[i] = va[i];
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
FBXExportProperty::FBXExportProperty(const std::vector<double>& va)
 | 
			
		||||
: type('d')
 | 
			
		||||
, data(8 * va.size()) {
 | 
			
		||||
    double* d = reinterpret_cast<double*>(data.data());
 | 
			
		||||
    for (size_t i = 0; i < va.size(); ++i) {
 | 
			
		||||
        d[i] = va[i];
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
FBXExportProperty::FBXExportProperty(const aiMatrix4x4& vm)
 | 
			
		||||
: type('d')
 | 
			
		||||
, data(8 * 16) {
 | 
			
		||||
    double* d = reinterpret_cast<double*>(data.data());
 | 
			
		||||
    for (unsigned int c = 0; c < 4; ++c) {
 | 
			
		||||
        for (unsigned int r = 0; r < 4; ++r) {
 | 
			
		||||
            d[4 * c + r] = vm[r][c];
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// public member functions
 | 
			
		||||
 | 
			
		||||
size_t FBXExportProperty::size() {
 | 
			
		||||
    switch (type) {
 | 
			
		||||
        case 'C':
 | 
			
		||||
        case 'Y':
 | 
			
		||||
        case 'I':
 | 
			
		||||
        case 'F':
 | 
			
		||||
        case 'D':
 | 
			
		||||
        case 'L':
 | 
			
		||||
            return data.size() + 1;
 | 
			
		||||
        case 'S':
 | 
			
		||||
        case 'R':
 | 
			
		||||
            return data.size() + 5;
 | 
			
		||||
        case 'i':
 | 
			
		||||
        case 'd':
 | 
			
		||||
            return data.size() + 13;
 | 
			
		||||
        default:
 | 
			
		||||
            throw DeadlyExportError("Requested size on property of unknown type");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void FBXExportProperty::DumpBinary(Assimp::StreamWriterLE& s) {
 | 
			
		||||
    s.PutU1(type);
 | 
			
		||||
    uint8_t* d = data.data();
 | 
			
		||||
    size_t N;
 | 
			
		||||
    switch (type) {
 | 
			
		||||
        case 'C': s.PutU1(*(reinterpret_cast<uint8_t*>(d))); return;
 | 
			
		||||
        case 'Y': s.PutI2(*(reinterpret_cast<int16_t*>(d))); return;
 | 
			
		||||
        case 'I': s.PutI4(*(reinterpret_cast<int32_t*>(d))); return;
 | 
			
		||||
        case 'F': s.PutF4(*(reinterpret_cast<float*>(d))); return;
 | 
			
		||||
        case 'D': s.PutF8(*(reinterpret_cast<double*>(d))); return;
 | 
			
		||||
        case 'L': s.PutI8(*(reinterpret_cast<int64_t*>(d))); return;
 | 
			
		||||
        case 'S':
 | 
			
		||||
        case 'R':
 | 
			
		||||
            s.PutU4(uint32_t(data.size()));
 | 
			
		||||
            for (size_t i = 0; i < data.size(); ++i) { s.PutU1(data[i]); }
 | 
			
		||||
            return;
 | 
			
		||||
        case 'i':
 | 
			
		||||
            N = data.size() / 4;
 | 
			
		||||
            s.PutU4(uint32_t(N)); // number of elements
 | 
			
		||||
            s.PutU4(0); // no encoding (1 would be zip-compressed)
 | 
			
		||||
            // TODO: compress if large?
 | 
			
		||||
            s.PutU4(uint32_t(data.size())); // data size
 | 
			
		||||
            for (size_t i = 0; i < N; ++i) {
 | 
			
		||||
                s.PutI4((reinterpret_cast<int32_t*>(d))[i]);
 | 
			
		||||
            }
 | 
			
		||||
            return;
 | 
			
		||||
        case 'l':
 | 
			
		||||
            N = data.size() / 8;
 | 
			
		||||
            s.PutU4(uint32_t(N)); // number of elements
 | 
			
		||||
            s.PutU4(0); // no encoding (1 would be zip-compressed)
 | 
			
		||||
            // TODO: compress if large?
 | 
			
		||||
            s.PutU4(uint32_t(data.size())); // data size
 | 
			
		||||
            for (size_t i = 0; i < N; ++i) {
 | 
			
		||||
                s.PutI8((reinterpret_cast<int64_t*>(d))[i]);
 | 
			
		||||
            }
 | 
			
		||||
            return;
 | 
			
		||||
        case 'f':
 | 
			
		||||
            N = data.size() / 4;
 | 
			
		||||
            s.PutU4(uint32_t(N)); // number of elements
 | 
			
		||||
            s.PutU4(0); // no encoding (1 would be zip-compressed)
 | 
			
		||||
            // TODO: compress if large?
 | 
			
		||||
            s.PutU4(uint32_t(data.size())); // data size
 | 
			
		||||
            for (size_t i = 0; i < N; ++i) {
 | 
			
		||||
                s.PutF4((reinterpret_cast<float*>(d))[i]);
 | 
			
		||||
            }
 | 
			
		||||
            return;
 | 
			
		||||
        case 'd':
 | 
			
		||||
            N = data.size() / 8;
 | 
			
		||||
            s.PutU4(uint32_t(N)); // number of elements
 | 
			
		||||
            s.PutU4(0); // no encoding (1 would be zip-compressed)
 | 
			
		||||
            // TODO: compress if large?
 | 
			
		||||
            s.PutU4(uint32_t(data.size())); // data size
 | 
			
		||||
            for (size_t i = 0; i < N; ++i) {
 | 
			
		||||
                s.PutF8((reinterpret_cast<double*>(d))[i]);
 | 
			
		||||
            }
 | 
			
		||||
            return;
 | 
			
		||||
        default:
 | 
			
		||||
            std::ostringstream err;
 | 
			
		||||
            err << "Tried to dump property with invalid type '";
 | 
			
		||||
            err << type << "'!";
 | 
			
		||||
            throw DeadlyExportError(err.str());
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void FBXExportProperty::DumpAscii(Assimp::StreamWriterLE& outstream, int indent) {
 | 
			
		||||
    std::ostringstream ss;
 | 
			
		||||
    ss.imbue(std::locale::classic());
 | 
			
		||||
    ss.precision(15); // this seems to match official FBX SDK exports
 | 
			
		||||
    DumpAscii(ss, indent);
 | 
			
		||||
    outstream.PutString(ss.str());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void FBXExportProperty::DumpAscii(std::ostream& s, int indent) {
 | 
			
		||||
    // no writing type... or anything. just shove it into the stream.
 | 
			
		||||
    uint8_t* d = data.data();
 | 
			
		||||
    size_t N;
 | 
			
		||||
    size_t swap = data.size();
 | 
			
		||||
    size_t count = 0;
 | 
			
		||||
    switch (type) {
 | 
			
		||||
    case 'C':
 | 
			
		||||
        if (*(reinterpret_cast<uint8_t*>(d))) { s << 'T'; }
 | 
			
		||||
        else { s << 'F'; }
 | 
			
		||||
        return;
 | 
			
		||||
    case 'Y': s << *(reinterpret_cast<int16_t*>(d)); return;
 | 
			
		||||
    case 'I': s << *(reinterpret_cast<int32_t*>(d)); return;
 | 
			
		||||
    case 'F': s << *(reinterpret_cast<float*>(d)); return;
 | 
			
		||||
    case 'D': s << *(reinterpret_cast<double*>(d)); return;
 | 
			
		||||
    case 'L': s << *(reinterpret_cast<int64_t*>(d)); return;
 | 
			
		||||
    case 'S':
 | 
			
		||||
        // first search to see if it has "\x00\x01" in it -
 | 
			
		||||
        // which separates fields which are reversed in the ascii version.
 | 
			
		||||
        // yeah.
 | 
			
		||||
        // FBX, yeah.
 | 
			
		||||
        for (size_t i = 0; i < data.size(); ++i) {
 | 
			
		||||
            if (data[i] == '\0') {
 | 
			
		||||
                swap = i;
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    case 'R':
 | 
			
		||||
        s << '"';
 | 
			
		||||
        // we might as well check this now,
 | 
			
		||||
        // probably it will never happen
 | 
			
		||||
        for (size_t i = 0; i < data.size(); ++i) {
 | 
			
		||||
            char c = data[i];
 | 
			
		||||
            if (c == '"') {
 | 
			
		||||
                throw runtime_error("can't handle quotes in property string");
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        // first write the SWAPPED member (if any)
 | 
			
		||||
        for (size_t i = swap + 2; i < data.size(); ++i) {
 | 
			
		||||
            char c = data[i];
 | 
			
		||||
            s << c;
 | 
			
		||||
        }
 | 
			
		||||
        // then a separator
 | 
			
		||||
        if (swap != data.size()) {
 | 
			
		||||
            s << "::";
 | 
			
		||||
        }
 | 
			
		||||
        // then the initial member
 | 
			
		||||
        for (size_t i = 0; i < swap; ++i) {
 | 
			
		||||
            char c = data[i];
 | 
			
		||||
            s << c;
 | 
			
		||||
        }
 | 
			
		||||
        s << '"';
 | 
			
		||||
        return;
 | 
			
		||||
    case 'i':
 | 
			
		||||
        N = data.size() / 4; // number of elements
 | 
			
		||||
        s << '*' << N << " {\n";
 | 
			
		||||
        for (int i = 0; i < indent + 1; ++i) { s << '\t'; }
 | 
			
		||||
        s << "a: ";
 | 
			
		||||
        for (size_t i = 0; i < N; ++i) {
 | 
			
		||||
            if (i > 0) { s << ','; }
 | 
			
		||||
            if (count++ > 120) { s << '\n'; count = 0; }
 | 
			
		||||
            s << (reinterpret_cast<int32_t*>(d))[i];
 | 
			
		||||
        }
 | 
			
		||||
        s << '\n';
 | 
			
		||||
        for (int i = 0; i < indent; ++i) { s << '\t'; }
 | 
			
		||||
        s << "} ";
 | 
			
		||||
        return;
 | 
			
		||||
    case 'l':
 | 
			
		||||
        N = data.size() / 8;
 | 
			
		||||
        s << '*' << N << " {\n";
 | 
			
		||||
        for (int i = 0; i < indent + 1; ++i) { s << '\t'; }
 | 
			
		||||
        s << "a: ";
 | 
			
		||||
        for (size_t i = 0; i < N; ++i) {
 | 
			
		||||
            if (i > 0) { s << ','; }
 | 
			
		||||
            if (count++ > 120) { s << '\n'; count = 0; }
 | 
			
		||||
            s << (reinterpret_cast<int64_t*>(d))[i];
 | 
			
		||||
        }
 | 
			
		||||
        s << '\n';
 | 
			
		||||
        for (int i = 0; i < indent; ++i) { s << '\t'; }
 | 
			
		||||
        s << "} ";
 | 
			
		||||
        return;
 | 
			
		||||
    case 'f':
 | 
			
		||||
        N = data.size() / 4;
 | 
			
		||||
        s << '*' << N << " {\n";
 | 
			
		||||
        for (int i = 0; i < indent + 1; ++i) { s << '\t'; }
 | 
			
		||||
        s << "a: ";
 | 
			
		||||
        for (size_t i = 0; i < N; ++i) {
 | 
			
		||||
            if (i > 0) { s << ','; }
 | 
			
		||||
            if (count++ > 120) { s << '\n'; count = 0; }
 | 
			
		||||
            s << (reinterpret_cast<float*>(d))[i];
 | 
			
		||||
        }
 | 
			
		||||
        s << '\n';
 | 
			
		||||
        for (int i = 0; i < indent; ++i) { s << '\t'; }
 | 
			
		||||
        s << "} ";
 | 
			
		||||
        return;
 | 
			
		||||
    case 'd':
 | 
			
		||||
        N = data.size() / 8;
 | 
			
		||||
        s << '*' << N << " {\n";
 | 
			
		||||
        for (int i = 0; i < indent + 1; ++i) { s << '\t'; }
 | 
			
		||||
        s << "a: ";
 | 
			
		||||
        // set precision to something that can handle doubles
 | 
			
		||||
        s.precision(15);
 | 
			
		||||
        for (size_t i = 0; i < N; ++i) {
 | 
			
		||||
            if (i > 0) { s << ','; }
 | 
			
		||||
            if (count++ > 120) { s << '\n'; count = 0; }
 | 
			
		||||
            s << (reinterpret_cast<double*>(d))[i];
 | 
			
		||||
        }
 | 
			
		||||
        s << '\n';
 | 
			
		||||
        for (int i = 0; i < indent; ++i) { s << '\t'; }
 | 
			
		||||
        s << "} ";
 | 
			
		||||
        return;
 | 
			
		||||
    default:
 | 
			
		||||
        std::ostringstream err;
 | 
			
		||||
        err << "Tried to dump property with invalid type '";
 | 
			
		||||
        err << type << "'!";
 | 
			
		||||
        throw runtime_error(err.str());
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // Namespace FBX
 | 
			
		||||
} // Namespace Assimp
 | 
			
		||||
 | 
			
		||||
#endif // ASSIMP_BUILD_NO_FBX_EXPORTER
 | 
			
		||||
#endif // ASSIMP_BUILD_NO_EXPORT
 | 
			
		||||
							
								
								
									
										129
									
								
								thirdparty/assimp/code/FBX/FBXExportProperty.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										129
									
								
								thirdparty/assimp/code/FBX/FBXExportProperty.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,129 @@
 | 
			
		||||
/*
 | 
			
		||||
Open Asset Import Library (assimp)
 | 
			
		||||
----------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
Copyright (c) 2006-2019, 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 FBXExportProperty.h
 | 
			
		||||
* Declares the FBX::Property helper class for fbx export.
 | 
			
		||||
*/
 | 
			
		||||
#ifndef AI_FBXEXPORTPROPERTY_H_INC
 | 
			
		||||
#define AI_FBXEXPORTPROPERTY_H_INC
 | 
			
		||||
 | 
			
		||||
#ifndef ASSIMP_BUILD_NO_FBX_EXPORTER
 | 
			
		||||
 | 
			
		||||
#include <assimp/types.h> // aiMatrix4x4
 | 
			
		||||
#include <assimp/StreamWriter.h> // StreamWriterLE
 | 
			
		||||
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <vector>
 | 
			
		||||
#include <ostream>
 | 
			
		||||
#include <type_traits> // is_void
 | 
			
		||||
 | 
			
		||||
namespace Assimp {
 | 
			
		||||
namespace FBX {
 | 
			
		||||
 | 
			
		||||
/** @brief FBX::Property
 | 
			
		||||
 *
 | 
			
		||||
 *  Holds a value of any of FBX's recognized types,
 | 
			
		||||
 *  each represented by a particular one-character code.
 | 
			
		||||
 *  C : 1-byte uint8, usually 0x00 or 0x01 to represent boolean false and true
 | 
			
		||||
 *  Y : 2-byte int16
 | 
			
		||||
 *  I : 4-byte int32
 | 
			
		||||
 *  F : 4-byte float
 | 
			
		||||
 *  D : 8-byte double
 | 
			
		||||
 *  L : 8-byte int64
 | 
			
		||||
 *  i : array of int32
 | 
			
		||||
 *  f : array of float
 | 
			
		||||
 *  d : array of double
 | 
			
		||||
 *  l : array of int64
 | 
			
		||||
 *  b : array of 1-byte booleans (0x00 or 0x01)
 | 
			
		||||
 *  S : string (array of 1-byte char)
 | 
			
		||||
 *  R : raw data (array of bytes)
 | 
			
		||||
 */
 | 
			
		||||
class FBXExportProperty {
 | 
			
		||||
public:
 | 
			
		||||
    // constructors for basic types.
 | 
			
		||||
    // all explicit to avoid accidental typecasting
 | 
			
		||||
    explicit FBXExportProperty(bool v);
 | 
			
		||||
    // TODO: determine if there is actually a byte type,
 | 
			
		||||
    // or if this always means <bool>. 'C' seems to imply <char>,
 | 
			
		||||
    // so possibly the above was intended to represent both.
 | 
			
		||||
    explicit FBXExportProperty(int16_t v);
 | 
			
		||||
    explicit FBXExportProperty(int32_t v);
 | 
			
		||||
    explicit FBXExportProperty(float v);
 | 
			
		||||
    explicit FBXExportProperty(double v);
 | 
			
		||||
    explicit FBXExportProperty(int64_t v);
 | 
			
		||||
    // strings can either be stored as 'R' (raw) or 'S' (string) type
 | 
			
		||||
    explicit FBXExportProperty(const char* c, bool raw = false);
 | 
			
		||||
    explicit FBXExportProperty(const std::string& s, bool raw = false);
 | 
			
		||||
    explicit FBXExportProperty(const std::vector<uint8_t>& r);
 | 
			
		||||
    explicit FBXExportProperty(const std::vector<int32_t>& va);
 | 
			
		||||
    explicit FBXExportProperty(const std::vector<int64_t>& va);
 | 
			
		||||
    explicit FBXExportProperty(const std::vector<double>& va);
 | 
			
		||||
    explicit FBXExportProperty(const std::vector<float>& va);
 | 
			
		||||
    explicit FBXExportProperty(const aiMatrix4x4& vm);
 | 
			
		||||
 | 
			
		||||
    // this will catch any type not defined above,
 | 
			
		||||
    // so that we don't accidentally convert something we don't want.
 | 
			
		||||
    // for example (const char*) --> (bool)... seriously wtf C++
 | 
			
		||||
    template <class T>
 | 
			
		||||
    explicit FBXExportProperty(T v) : type('X') {
 | 
			
		||||
        static_assert(std::is_void<T>::value, "TRIED TO CREATE FBX PROPERTY WITH UNSUPPORTED TYPE, CHECK YOUR PROPERTY INSTANTIATION");
 | 
			
		||||
    } // note: no line wrap so it appears verbatim on the compiler error
 | 
			
		||||
 | 
			
		||||
    // the size of this property node in a binary file, in bytes
 | 
			
		||||
    size_t size();
 | 
			
		||||
 | 
			
		||||
    // write this property node as binary data to the given stream
 | 
			
		||||
    void DumpBinary(Assimp::StreamWriterLE& s);
 | 
			
		||||
    void DumpAscii(Assimp::StreamWriterLE& s, int indent = 0);
 | 
			
		||||
    void DumpAscii(std::ostream& s, int indent = 0);
 | 
			
		||||
    // note: make sure the ostream is in classic "C" locale
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    char type;
 | 
			
		||||
    std::vector<uint8_t> data;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
} // Namespace FBX
 | 
			
		||||
} // Namespace Assimp
 | 
			
		||||
 | 
			
		||||
#endif // ASSIMP_BUILD_NO_FBX_EXPORTER
 | 
			
		||||
 | 
			
		||||
#endif // AI_FBXEXPORTPROPERTY_H_INC
 | 
			
		||||
							
								
								
									
										2556
									
								
								thirdparty/assimp/code/FBX/FBXExporter.cpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										2556
									
								
								thirdparty/assimp/code/FBX/FBXExporter.cpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										178
									
								
								thirdparty/assimp/code/FBX/FBXExporter.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										178
									
								
								thirdparty/assimp/code/FBX/FBXExporter.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,178 @@
 | 
			
		||||
/*
 | 
			
		||||
Open Asset Import Library (assimp)
 | 
			
		||||
----------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
Copyright (c) 2006-2019, 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 FBXExporter.h
 | 
			
		||||
* Declares the exporter class to write a scene to an fbx file
 | 
			
		||||
*/
 | 
			
		||||
#ifndef AI_FBXEXPORTER_H_INC
 | 
			
		||||
#define AI_FBXEXPORTER_H_INC
 | 
			
		||||
 | 
			
		||||
#ifndef ASSIMP_BUILD_NO_FBX_EXPORTER
 | 
			
		||||
 | 
			
		||||
#include "FBXExportNode.h" // FBX::Node
 | 
			
		||||
#include "FBXCommon.h" // FBX::TransformInheritance
 | 
			
		||||
 | 
			
		||||
#include <assimp/types.h>
 | 
			
		||||
//#include <assimp/material.h>
 | 
			
		||||
#include <assimp/StreamWriter.h> // StreamWriterLE
 | 
			
		||||
#include <assimp/Exceptional.h> // DeadlyExportError
 | 
			
		||||
 | 
			
		||||
#include <vector>
 | 
			
		||||
#include <map>
 | 
			
		||||
#include <unordered_set>
 | 
			
		||||
#include <memory> // shared_ptr
 | 
			
		||||
#include <sstream> // stringstream
 | 
			
		||||
 | 
			
		||||
struct aiScene;
 | 
			
		||||
struct aiNode;
 | 
			
		||||
//struct aiMaterial;
 | 
			
		||||
 | 
			
		||||
namespace Assimp
 | 
			
		||||
{
 | 
			
		||||
    class IOSystem;
 | 
			
		||||
    class IOStream;
 | 
			
		||||
    class ExportProperties;
 | 
			
		||||
 | 
			
		||||
    // ---------------------------------------------------------------------
 | 
			
		||||
    /** Helper class to export a given scene to an FBX file. */
 | 
			
		||||
    // ---------------------------------------------------------------------
 | 
			
		||||
    class FBXExporter
 | 
			
		||||
    {
 | 
			
		||||
    public:
 | 
			
		||||
        /// Constructor for a specific scene to export
 | 
			
		||||
        FBXExporter(const aiScene* pScene, const ExportProperties* pProperties);
 | 
			
		||||
 | 
			
		||||
        // call one of these methods to export
 | 
			
		||||
        void ExportBinary(const char* pFile, IOSystem* pIOSystem);
 | 
			
		||||
        void ExportAscii(const char* pFile, IOSystem* pIOSystem);
 | 
			
		||||
 | 
			
		||||
    private:
 | 
			
		||||
        bool binary; // whether current export is in binary or ascii format
 | 
			
		||||
        const aiScene* mScene; // the scene to export
 | 
			
		||||
        const ExportProperties* mProperties; // currently unused
 | 
			
		||||
        std::shared_ptr<IOStream> outfile; // file to write to
 | 
			
		||||
 | 
			
		||||
        std::vector<FBX::Node> connections; // connection storage
 | 
			
		||||
 | 
			
		||||
        std::vector<int64_t> mesh_uids;
 | 
			
		||||
        std::vector<int64_t> material_uids;
 | 
			
		||||
        std::map<const aiNode*,int64_t> node_uids;
 | 
			
		||||
 | 
			
		||||
        // this crude unique-ID system is actually fine
 | 
			
		||||
        int64_t last_uid = 999999;
 | 
			
		||||
        int64_t generate_uid() { return ++last_uid; }
 | 
			
		||||
 | 
			
		||||
        // binary files have a specific header and footer,
 | 
			
		||||
        // in addition to the actual data
 | 
			
		||||
        void WriteBinaryHeader();
 | 
			
		||||
        void WriteBinaryFooter();
 | 
			
		||||
 | 
			
		||||
        // ascii files have a comment at the top
 | 
			
		||||
        void WriteAsciiHeader();
 | 
			
		||||
 | 
			
		||||
        // WriteAllNodes does the actual export.
 | 
			
		||||
        // It just calls all the Write<Section> methods below in order.
 | 
			
		||||
        void WriteAllNodes();
 | 
			
		||||
 | 
			
		||||
        // Methods to write individual sections.
 | 
			
		||||
        // The order here matches the order inside an FBX file.
 | 
			
		||||
        // Each method corresponds to a top-level FBX section,
 | 
			
		||||
        // except WriteHeader which also includes some binary-only sections
 | 
			
		||||
        // and WriteFooter which is binary data only.
 | 
			
		||||
        void WriteHeaderExtension();
 | 
			
		||||
        // WriteFileId(); // binary-only, included in WriteHeader
 | 
			
		||||
        // WriteCreationTime(); // binary-only, included in WriteHeader
 | 
			
		||||
        // WriteCreator(); // binary-only, included in WriteHeader
 | 
			
		||||
        void WriteGlobalSettings();
 | 
			
		||||
        void WriteDocuments();
 | 
			
		||||
        void WriteReferences();
 | 
			
		||||
        void WriteDefinitions();
 | 
			
		||||
        void WriteObjects();
 | 
			
		||||
        void WriteConnections();
 | 
			
		||||
        // WriteTakes(); // deprecated since at least 2015 (fbx 7.4)
 | 
			
		||||
 | 
			
		||||
        // helpers
 | 
			
		||||
        void WriteAsciiSectionHeader(const std::string& title);
 | 
			
		||||
        void WriteModelNodes(
 | 
			
		||||
            Assimp::StreamWriterLE& s,
 | 
			
		||||
            const aiNode* node,
 | 
			
		||||
            int64_t parent_uid,
 | 
			
		||||
            const std::unordered_set<const aiNode*>& limbnodes
 | 
			
		||||
        );
 | 
			
		||||
        void WriteModelNodes( // usually don't call this directly
 | 
			
		||||
            StreamWriterLE& s,
 | 
			
		||||
            const aiNode* node,
 | 
			
		||||
            int64_t parent_uid,
 | 
			
		||||
            const std::unordered_set<const aiNode*>& limbnodes,
 | 
			
		||||
            std::vector<std::pair<std::string,aiVector3D>>& transform_chain
 | 
			
		||||
        );
 | 
			
		||||
        void WriteModelNode( // nor this
 | 
			
		||||
            StreamWriterLE& s,
 | 
			
		||||
            bool binary,
 | 
			
		||||
            const aiNode* node,
 | 
			
		||||
            int64_t node_uid,
 | 
			
		||||
            const std::string& type,
 | 
			
		||||
            const std::vector<std::pair<std::string,aiVector3D>>& xfm_chain,
 | 
			
		||||
            FBX::TransformInheritance ti_type=FBX::TransformInheritance_RSrs
 | 
			
		||||
        );
 | 
			
		||||
        void WriteAnimationCurveNode(
 | 
			
		||||
            StreamWriterLE& outstream,
 | 
			
		||||
            int64_t uid,
 | 
			
		||||
            const std::string& name, // "T", "R", or "S"
 | 
			
		||||
            aiVector3D default_value,
 | 
			
		||||
            std::string property_name, // "Lcl Translation" etc
 | 
			
		||||
            int64_t animation_layer_uid,
 | 
			
		||||
            int64_t node_uid
 | 
			
		||||
        );
 | 
			
		||||
        void WriteAnimationCurve(
 | 
			
		||||
            StreamWriterLE& outstream,
 | 
			
		||||
            double default_value,
 | 
			
		||||
            const std::vector<int64_t>& times,
 | 
			
		||||
            const std::vector<float>& values,
 | 
			
		||||
            int64_t curvenode_id,
 | 
			
		||||
            const std::string& property_link // "d|X", "d|Y", etc
 | 
			
		||||
        );
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif // ASSIMP_BUILD_NO_FBX_EXPORTER
 | 
			
		||||
 | 
			
		||||
#endif // AI_FBXEXPORTER_H_INC
 | 
			
		||||
							
								
								
									
										164
									
								
								thirdparty/assimp/code/FBX/FBXImportSettings.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										164
									
								
								thirdparty/assimp/code/FBX/FBXImportSettings.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,164 @@
 | 
			
		||||
/*
 | 
			
		||||
Open Asset Import Library (assimp)
 | 
			
		||||
----------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
Copyright (c) 2006-2019, 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  FBXImportSettings.h
 | 
			
		||||
 *  @brief FBX importer runtime configuration
 | 
			
		||||
 */
 | 
			
		||||
#ifndef INCLUDED_AI_FBX_IMPORTSETTINGS_H
 | 
			
		||||
#define INCLUDED_AI_FBX_IMPORTSETTINGS_H
 | 
			
		||||
 | 
			
		||||
namespace Assimp {
 | 
			
		||||
namespace FBX {
 | 
			
		||||
 | 
			
		||||
/** FBX import settings, parts of which are publicly accessible via their corresponding AI_CONFIG constants */
 | 
			
		||||
struct ImportSettings
 | 
			
		||||
{
 | 
			
		||||
    ImportSettings()
 | 
			
		||||
    : strictMode(true)
 | 
			
		||||
    , readAllLayers(true)
 | 
			
		||||
    , readAllMaterials(false)
 | 
			
		||||
    , readMaterials(true)
 | 
			
		||||
    , readTextures(true)
 | 
			
		||||
    , readCameras(true)
 | 
			
		||||
    , readLights(true)
 | 
			
		||||
    , readAnimations(true)
 | 
			
		||||
    , readWeights(true)
 | 
			
		||||
    , preservePivots(true)
 | 
			
		||||
    , optimizeEmptyAnimationCurves(true)
 | 
			
		||||
    , useLegacyEmbeddedTextureNaming(false)
 | 
			
		||||
    , removeEmptyBones( true )
 | 
			
		||||
    , convertToMeters( false ) {
 | 
			
		||||
        // empty
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /** enable strict mode:
 | 
			
		||||
     *   - only accept fbx 2012, 2013 files
 | 
			
		||||
     *   - on the slightest error, give up.
 | 
			
		||||
     *
 | 
			
		||||
     *  Basically, strict mode means that the fbx file will actually
 | 
			
		||||
     *  be validated. Strict mode is off by default. */
 | 
			
		||||
    bool strictMode;
 | 
			
		||||
 | 
			
		||||
    /** specifies whether all geometry layers are read and scanned for
 | 
			
		||||
      * usable data channels. The FBX spec indicates that many readers
 | 
			
		||||
      * will only read the first channel and that this is in some way
 | 
			
		||||
      * the recommended way- in reality, however, it happens a lot that
 | 
			
		||||
      * vertex data is spread among multiple layers. The default
 | 
			
		||||
      * value for this option is true.*/
 | 
			
		||||
    bool readAllLayers;
 | 
			
		||||
 | 
			
		||||
    /** specifies whether all materials are read, or only those that
 | 
			
		||||
     *  are referenced by at least one mesh. Reading all materials
 | 
			
		||||
     *  may make FBX reading a lot slower since all objects
 | 
			
		||||
     *  need to be processed .
 | 
			
		||||
     *  This bit is ignored unless readMaterials=true*/
 | 
			
		||||
    bool readAllMaterials;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /** import materials (true) or skip them and assign a default
 | 
			
		||||
     *  material. The default value is true.*/
 | 
			
		||||
    bool readMaterials;
 | 
			
		||||
 | 
			
		||||
    /** import embedded textures? Default value is true.*/
 | 
			
		||||
    bool readTextures;
 | 
			
		||||
 | 
			
		||||
    /** import cameras? Default value is true.*/
 | 
			
		||||
    bool readCameras;
 | 
			
		||||
 | 
			
		||||
    /** import light sources? Default value is true.*/
 | 
			
		||||
    bool readLights;
 | 
			
		||||
 | 
			
		||||
    /** import animations (i.e. animation curves, the node
 | 
			
		||||
     *  skeleton is always imported). Default value is true. */
 | 
			
		||||
    bool readAnimations;
 | 
			
		||||
 | 
			
		||||
    /** read bones (vertex weights and deform info).
 | 
			
		||||
     *  Default value is true. */
 | 
			
		||||
    bool readWeights;
 | 
			
		||||
 | 
			
		||||
    /** preserve transformation pivots and offsets. Since these can
 | 
			
		||||
     *  not directly be represented in assimp, additional dummy
 | 
			
		||||
     *  nodes will be generated. Note that settings this to false
 | 
			
		||||
     *  can make animation import a lot slower. The default value
 | 
			
		||||
     *  is true.
 | 
			
		||||
     *
 | 
			
		||||
     *  The naming scheme for the generated nodes is:
 | 
			
		||||
     *    <OriginalName>_$AssimpFbx$_<TransformName>
 | 
			
		||||
     *
 | 
			
		||||
     *  where <TransformName> is one of
 | 
			
		||||
     *    RotationPivot
 | 
			
		||||
     *    RotationOffset
 | 
			
		||||
     *    PreRotation
 | 
			
		||||
     *    PostRotation
 | 
			
		||||
     *    ScalingPivot
 | 
			
		||||
     *    ScalingOffset
 | 
			
		||||
     *    Translation
 | 
			
		||||
     *    Scaling
 | 
			
		||||
     *    Rotation
 | 
			
		||||
     **/
 | 
			
		||||
    bool preservePivots;
 | 
			
		||||
 | 
			
		||||
    /** do not import animation curves that specify a constant
 | 
			
		||||
     *  values matching the corresponding node transformation.
 | 
			
		||||
     *  The default value is true. */
 | 
			
		||||
    bool optimizeEmptyAnimationCurves;
 | 
			
		||||
 | 
			
		||||
    /** use legacy naming for embedded textures eg: (*0, *1, *2)
 | 
			
		||||
    */
 | 
			
		||||
    bool useLegacyEmbeddedTextureNaming;
 | 
			
		||||
 | 
			
		||||
    /** Empty bones shall be removed
 | 
			
		||||
    */
 | 
			
		||||
    bool removeEmptyBones;
 | 
			
		||||
 | 
			
		||||
    /** Set to true to perform a conversion from cm to meter after the import
 | 
			
		||||
    */
 | 
			
		||||
    bool convertToMeters;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
} // !FBX
 | 
			
		||||
} // !Assimp
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										206
									
								
								thirdparty/assimp/code/FBX/FBXImporter.cpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										206
									
								
								thirdparty/assimp/code/FBX/FBXImporter.cpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,206 @@
 | 
			
		||||
/*
 | 
			
		||||
Open Asset Import Library (assimp)
 | 
			
		||||
----------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
Copyright (c) 2006-2019, 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.
 | 
			
		||||
r
 | 
			
		||||
* 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  FBXImporter.cpp
 | 
			
		||||
 *  @brief Implementation of the FBX importer.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef ASSIMP_BUILD_NO_FBX_IMPORTER
 | 
			
		||||
 | 
			
		||||
#include "FBXImporter.h"
 | 
			
		||||
 | 
			
		||||
#include "FBXTokenizer.h"
 | 
			
		||||
#include "FBXParser.h"
 | 
			
		||||
#include "FBXUtil.h"
 | 
			
		||||
#include "FBXDocument.h"
 | 
			
		||||
#include "FBXConverter.h"
 | 
			
		||||
 | 
			
		||||
#include <assimp/StreamReader.h>
 | 
			
		||||
#include <assimp/MemoryIOWrapper.h>
 | 
			
		||||
#include <assimp/Importer.hpp>
 | 
			
		||||
#include <assimp/importerdesc.h>
 | 
			
		||||
 | 
			
		||||
namespace Assimp {
 | 
			
		||||
 | 
			
		||||
template<>
 | 
			
		||||
const char* LogFunctions<FBXImporter>::Prefix() {
 | 
			
		||||
    static auto prefix = "FBX: ";
 | 
			
		||||
    return prefix;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
using namespace Assimp;
 | 
			
		||||
using namespace Assimp::Formatter;
 | 
			
		||||
using namespace Assimp::FBX;
 | 
			
		||||
 | 
			
		||||
namespace {
 | 
			
		||||
 | 
			
		||||
static const aiImporterDesc desc = {
 | 
			
		||||
    "Autodesk FBX Importer",
 | 
			
		||||
    "",
 | 
			
		||||
    "",
 | 
			
		||||
    "",
 | 
			
		||||
    aiImporterFlags_SupportTextFlavour,
 | 
			
		||||
    0,
 | 
			
		||||
    0,
 | 
			
		||||
    0,
 | 
			
		||||
    0,
 | 
			
		||||
    "fbx"
 | 
			
		||||
};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
// Constructor to be privately used by #Importer
 | 
			
		||||
FBXImporter::FBXImporter()
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
// Destructor, private as well
 | 
			
		||||
FBXImporter::~FBXImporter()
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
// Returns whether the class can handle the format of the given file.
 | 
			
		||||
bool FBXImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const
 | 
			
		||||
{
 | 
			
		||||
    const std::string& extension = GetExtension(pFile);
 | 
			
		||||
    if (extension == std::string( desc.mFileExtensions ) ) {
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    else if ((!extension.length() || checkSig) && pIOHandler)   {
 | 
			
		||||
        // at least ASCII-FBX files usually have a 'FBX' somewhere in their head
 | 
			
		||||
        const char* tokens[] = {"fbx"};
 | 
			
		||||
        return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1);
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
// List all extensions handled by this loader
 | 
			
		||||
const aiImporterDesc* FBXImporter::GetInfo () const
 | 
			
		||||
{
 | 
			
		||||
    return &desc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
// Setup configuration properties for the loader
 | 
			
		||||
void FBXImporter::SetupProperties(const Importer* pImp)
 | 
			
		||||
{
 | 
			
		||||
    settings.readAllLayers = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_ALL_GEOMETRY_LAYERS, true);
 | 
			
		||||
    settings.readAllMaterials = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_ALL_MATERIALS, false);
 | 
			
		||||
    settings.readMaterials = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_MATERIALS, true);
 | 
			
		||||
    settings.readTextures = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_TEXTURES, true);
 | 
			
		||||
    settings.readCameras = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_CAMERAS, true);
 | 
			
		||||
    settings.readLights = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_LIGHTS, true);
 | 
			
		||||
    settings.readAnimations = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_ANIMATIONS, true);
 | 
			
		||||
    settings.strictMode = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_STRICT_MODE, false);
 | 
			
		||||
    settings.preservePivots = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_PRESERVE_PIVOTS, true);
 | 
			
		||||
    settings.optimizeEmptyAnimationCurves = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_OPTIMIZE_EMPTY_ANIMATION_CURVES, true);
 | 
			
		||||
    settings.useLegacyEmbeddedTextureNaming = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_EMBEDDED_TEXTURES_LEGACY_NAMING, false);
 | 
			
		||||
    settings.removeEmptyBones = pImp->GetPropertyBool(AI_CONFIG_IMPORT_REMOVE_EMPTY_BONES, true);
 | 
			
		||||
    settings.convertToMeters = pImp->GetPropertyBool(AI_CONFIG_FBX_CONVERT_TO_M, false);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
// Imports the given file into the given scene structure.
 | 
			
		||||
void FBXImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler)
 | 
			
		||||
{
 | 
			
		||||
    std::unique_ptr<IOStream> stream(pIOHandler->Open(pFile,"rb"));
 | 
			
		||||
    if (!stream) {
 | 
			
		||||
        ThrowException("Could not open file for reading");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // read entire file into memory - no streaming for this, fbx
 | 
			
		||||
    // files can grow large, but the assimp output data structure
 | 
			
		||||
    // then becomes very large, too. Assimp doesn't support
 | 
			
		||||
    // streaming for its output data structures so the net win with
 | 
			
		||||
    // streaming input data would be very low.
 | 
			
		||||
    std::vector<char> contents;
 | 
			
		||||
    contents.resize(stream->FileSize()+1);
 | 
			
		||||
    stream->Read( &*contents.begin(), 1, contents.size()-1 );
 | 
			
		||||
    contents[ contents.size() - 1 ] = 0;
 | 
			
		||||
    const char* const begin = &*contents.begin();
 | 
			
		||||
 | 
			
		||||
    // broadphase tokenizing pass in which we identify the core
 | 
			
		||||
    // syntax elements of FBX (brackets, commas, key:value mappings)
 | 
			
		||||
    TokenList tokens;
 | 
			
		||||
    try {
 | 
			
		||||
 | 
			
		||||
        bool is_binary = false;
 | 
			
		||||
        if (!strncmp(begin,"Kaydara FBX Binary",18)) {
 | 
			
		||||
            is_binary = true;
 | 
			
		||||
            TokenizeBinary(tokens,begin,contents.size());
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
            Tokenize(tokens,begin);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // use this information to construct a very rudimentary
 | 
			
		||||
        // parse-tree representing the FBX scope structure
 | 
			
		||||
        Parser parser(tokens, is_binary);
 | 
			
		||||
 | 
			
		||||
        // take the raw parse-tree and convert it to a FBX DOM
 | 
			
		||||
        Document doc(parser,settings);
 | 
			
		||||
 | 
			
		||||
        // convert the FBX DOM to aiScene
 | 
			
		||||
        ConvertToAssimpScene(pScene, doc, settings.removeEmptyBones);
 | 
			
		||||
 | 
			
		||||
        // size relative to cm
 | 
			
		||||
        float size_relative_to_cm = doc.GlobalSettings().UnitScaleFactor();
 | 
			
		||||
 | 
			
		||||
        // Set FBX file scale is relative to CM must be converted to M for
 | 
			
		||||
        // 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;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif // !ASSIMP_BUILD_NO_FBX_IMPORTER
 | 
			
		||||
							
								
								
									
										100
									
								
								thirdparty/assimp/code/FBX/FBXImporter.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										100
									
								
								thirdparty/assimp/code/FBX/FBXImporter.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,100 @@
 | 
			
		||||
/*
 | 
			
		||||
Open Asset Import Library (assimp)
 | 
			
		||||
----------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
Copyright (c) 2006-2019, 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  FBXImporter.h
 | 
			
		||||
 *  @brief Declaration of the FBX main importer class
 | 
			
		||||
 */
 | 
			
		||||
#ifndef INCLUDED_AI_FBX_IMPORTER_H
 | 
			
		||||
#define INCLUDED_AI_FBX_IMPORTER_H
 | 
			
		||||
 | 
			
		||||
#include <assimp/BaseImporter.h>
 | 
			
		||||
#include <assimp/LogAux.h>
 | 
			
		||||
 | 
			
		||||
#include "FBXImportSettings.h"
 | 
			
		||||
 | 
			
		||||
namespace Assimp    {
 | 
			
		||||
 | 
			
		||||
// TinyFormatter.h
 | 
			
		||||
namespace Formatter {
 | 
			
		||||
    template <typename T,typename TR, typename A> class basic_formatter;
 | 
			
		||||
    typedef class basic_formatter< char, std::char_traits<char>, std::allocator<char> > format;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// -------------------------------------------------------------------------------------------
 | 
			
		||||
/** Load the Autodesk FBX file format.
 | 
			
		||||
 | 
			
		||||
 See http://en.wikipedia.org/wiki/FBX
 | 
			
		||||
*/
 | 
			
		||||
// -------------------------------------------------------------------------------------------
 | 
			
		||||
class FBXImporter : public BaseImporter, public LogFunctions<FBXImporter>
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    FBXImporter();
 | 
			
		||||
    virtual ~FBXImporter();
 | 
			
		||||
 | 
			
		||||
    // --------------------
 | 
			
		||||
    bool CanRead( const std::string& pFile,
 | 
			
		||||
        IOSystem* pIOHandler,
 | 
			
		||||
        bool checkSig
 | 
			
		||||
    ) const;
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
 | 
			
		||||
    // --------------------
 | 
			
		||||
    const aiImporterDesc* GetInfo () const;
 | 
			
		||||
 | 
			
		||||
    // --------------------
 | 
			
		||||
    void SetupProperties(const Importer* pImp);
 | 
			
		||||
 | 
			
		||||
    // --------------------
 | 
			
		||||
    void InternReadFile( const std::string& pFile,
 | 
			
		||||
        aiScene* pScene,
 | 
			
		||||
        IOSystem* pIOHandler
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    FBX::ImportSettings settings;
 | 
			
		||||
}; // !class FBXImporter
 | 
			
		||||
 | 
			
		||||
} // end of namespace Assimp
 | 
			
		||||
#endif // !INCLUDED_AI_FBX_IMPORTER_H
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										405
									
								
								thirdparty/assimp/code/FBX/FBXMaterial.cpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										405
									
								
								thirdparty/assimp/code/FBX/FBXMaterial.cpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,405 @@
 | 
			
		||||
/*
 | 
			
		||||
Open Asset Import Library (assimp)
 | 
			
		||||
----------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
Copyright (c) 2006-2019, 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  FBXMaterial.cpp
 | 
			
		||||
 *  @brief Assimp::FBX::Material and Assimp::FBX::Texture implementation
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef ASSIMP_BUILD_NO_FBX_IMPORTER
 | 
			
		||||
 | 
			
		||||
#include "FBXParser.h"
 | 
			
		||||
#include "FBXDocument.h"
 | 
			
		||||
#include "FBXImporter.h"
 | 
			
		||||
#include "FBXImportSettings.h"
 | 
			
		||||
#include "FBXDocumentUtil.h"
 | 
			
		||||
#include "FBXProperties.h"
 | 
			
		||||
#include <assimp/ByteSwapper.h>
 | 
			
		||||
 | 
			
		||||
#include <algorithm> // std::transform
 | 
			
		||||
#include "FBXUtil.h"
 | 
			
		||||
 | 
			
		||||
namespace Assimp {
 | 
			
		||||
namespace FBX {
 | 
			
		||||
 | 
			
		||||
    using namespace Util;
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
Material::Material(uint64_t id, const Element& element, const Document& doc, const std::string& name)
 | 
			
		||||
: Object(id,element,name)
 | 
			
		||||
{
 | 
			
		||||
    const Scope& sc = GetRequiredScope(element);
 | 
			
		||||
 | 
			
		||||
    const Element* const ShadingModel = sc["ShadingModel"];
 | 
			
		||||
    const Element* const MultiLayer = sc["MultiLayer"];
 | 
			
		||||
 | 
			
		||||
    if(MultiLayer) {
 | 
			
		||||
        multilayer = !!ParseTokenAsInt(GetRequiredToken(*MultiLayer,0));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(ShadingModel) {
 | 
			
		||||
        shading = ParseTokenAsString(GetRequiredToken(*ShadingModel,0));
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
        DOMWarning("shading mode not specified, assuming phong",&element);
 | 
			
		||||
        shading = "phong";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::string templateName;
 | 
			
		||||
 | 
			
		||||
    // lower-case shading because Blender (for example) writes "Phong"
 | 
			
		||||
    std::transform(shading.begin(), shading.end(), shading.begin(), ::tolower);
 | 
			
		||||
    if(shading == "phong") {
 | 
			
		||||
        templateName = "Material.FbxSurfacePhong";
 | 
			
		||||
    }
 | 
			
		||||
    else if(shading == "lambert") {
 | 
			
		||||
        templateName = "Material.FbxSurfaceLambert";
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
        DOMWarning("shading mode not recognized: " + shading,&element);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    props = GetPropertyTable(doc,templateName,element,sc);
 | 
			
		||||
 | 
			
		||||
    // resolve texture links
 | 
			
		||||
    const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID());
 | 
			
		||||
    for(const Connection* con : conns) {
 | 
			
		||||
 | 
			
		||||
        // texture link to properties, not objects
 | 
			
		||||
        if (!con->PropertyName().length()) {
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const Object* const ob = con->SourceObject();
 | 
			
		||||
        if(!ob) {
 | 
			
		||||
            DOMWarning("failed to read source object for texture link, ignoring",&element);
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const Texture* const tex = dynamic_cast<const Texture*>(ob);
 | 
			
		||||
        if(!tex) {
 | 
			
		||||
            const LayeredTexture* const layeredTexture = dynamic_cast<const LayeredTexture*>(ob);
 | 
			
		||||
            if(!layeredTexture) {
 | 
			
		||||
                DOMWarning("source object for texture link is not a texture or layered texture, ignoring",&element);
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
            const std::string& prop = con->PropertyName();
 | 
			
		||||
            if (layeredTextures.find(prop) != layeredTextures.end()) {
 | 
			
		||||
                DOMWarning("duplicate layered texture link: " + prop,&element);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            layeredTextures[prop] = layeredTexture;
 | 
			
		||||
            ((LayeredTexture*)layeredTexture)->fillTexture(doc);
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            const std::string& prop = con->PropertyName();
 | 
			
		||||
            if (textures.find(prop) != textures.end()) {
 | 
			
		||||
                DOMWarning("duplicate texture link: " + prop,&element);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            textures[prop] = tex;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
Material::~Material()
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
Texture::Texture(uint64_t id, const Element& element, const Document& doc, const std::string& name)
 | 
			
		||||
: Object(id,element,name)
 | 
			
		||||
, uvScaling(1.0f,1.0f)
 | 
			
		||||
, media(0)
 | 
			
		||||
{
 | 
			
		||||
    const Scope& sc = GetRequiredScope(element);
 | 
			
		||||
 | 
			
		||||
    const Element* const Type = sc["Type"];
 | 
			
		||||
    const Element* const FileName = sc["FileName"];
 | 
			
		||||
    const Element* const RelativeFilename = sc["RelativeFilename"];
 | 
			
		||||
    const Element* const ModelUVTranslation = sc["ModelUVTranslation"];
 | 
			
		||||
    const Element* const ModelUVScaling = sc["ModelUVScaling"];
 | 
			
		||||
    const Element* const Texture_Alpha_Source = sc["Texture_Alpha_Source"];
 | 
			
		||||
    const Element* const Cropping = sc["Cropping"];
 | 
			
		||||
 | 
			
		||||
    if(Type) {
 | 
			
		||||
        type = ParseTokenAsString(GetRequiredToken(*Type,0));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(FileName) {
 | 
			
		||||
        fileName = ParseTokenAsString(GetRequiredToken(*FileName,0));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(RelativeFilename) {
 | 
			
		||||
        relativeFileName = ParseTokenAsString(GetRequiredToken(*RelativeFilename,0));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(ModelUVTranslation) {
 | 
			
		||||
        uvTrans = aiVector2D(ParseTokenAsFloat(GetRequiredToken(*ModelUVTranslation,0)),
 | 
			
		||||
            ParseTokenAsFloat(GetRequiredToken(*ModelUVTranslation,1))
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(ModelUVScaling) {
 | 
			
		||||
        uvScaling = aiVector2D(ParseTokenAsFloat(GetRequiredToken(*ModelUVScaling,0)),
 | 
			
		||||
            ParseTokenAsFloat(GetRequiredToken(*ModelUVScaling,1))
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(Cropping) {
 | 
			
		||||
        crop[0] = ParseTokenAsInt(GetRequiredToken(*Cropping,0));
 | 
			
		||||
        crop[1] = ParseTokenAsInt(GetRequiredToken(*Cropping,1));
 | 
			
		||||
        crop[2] = ParseTokenAsInt(GetRequiredToken(*Cropping,2));
 | 
			
		||||
        crop[3] = ParseTokenAsInt(GetRequiredToken(*Cropping,3));
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
        // vc8 doesn't support the crop() syntax in initialization lists
 | 
			
		||||
        // (and vc9 WARNS about the new (i.e. compliant) behaviour).
 | 
			
		||||
        crop[0] = crop[1] = crop[2] = crop[3] = 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(Texture_Alpha_Source) {
 | 
			
		||||
        alphaSource = ParseTokenAsString(GetRequiredToken(*Texture_Alpha_Source,0));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    props = GetPropertyTable(doc,"Texture.FbxFileTexture",element,sc);
 | 
			
		||||
 | 
			
		||||
    // 3DS Max and FBX SDK use "Scaling" and "Translation" instead of "ModelUVScaling" and "ModelUVTranslation". Use these properties if available.
 | 
			
		||||
    bool ok;
 | 
			
		||||
    const aiVector3D& scaling = PropertyGet<aiVector3D>(*props, "Scaling", ok);
 | 
			
		||||
    if (ok) {
 | 
			
		||||
        uvScaling.x = scaling.x;
 | 
			
		||||
        uvScaling.y = scaling.y;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const aiVector3D& trans = PropertyGet<aiVector3D>(*props, "Translation", ok);
 | 
			
		||||
    if (ok) {
 | 
			
		||||
        uvTrans.x = trans.x;
 | 
			
		||||
        uvTrans.y = trans.y;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // resolve video links
 | 
			
		||||
    if(doc.Settings().readTextures) {
 | 
			
		||||
        const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID());
 | 
			
		||||
        for(const Connection* con : conns) {
 | 
			
		||||
            const Object* const ob = con->SourceObject();
 | 
			
		||||
            if(!ob) {
 | 
			
		||||
                DOMWarning("failed to read source object for texture link, ignoring",&element);
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            const Video* const video = dynamic_cast<const Video*>(ob);
 | 
			
		||||
            if(video) {
 | 
			
		||||
                media = video;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Texture::~Texture()
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
LayeredTexture::LayeredTexture(uint64_t id, const Element& element, const Document& /*doc*/, const std::string& name)
 | 
			
		||||
: Object(id,element,name)
 | 
			
		||||
,blendMode(BlendMode_Modulate)
 | 
			
		||||
,alpha(1)
 | 
			
		||||
{
 | 
			
		||||
    const Scope& sc = GetRequiredScope(element);
 | 
			
		||||
 | 
			
		||||
    const Element* const BlendModes = sc["BlendModes"];
 | 
			
		||||
    const Element* const Alphas = sc["Alphas"];
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    if(BlendModes!=0)
 | 
			
		||||
    {
 | 
			
		||||
        blendMode = (BlendMode)ParseTokenAsInt(GetRequiredToken(*BlendModes,0));
 | 
			
		||||
    }
 | 
			
		||||
    if(Alphas!=0)
 | 
			
		||||
    {
 | 
			
		||||
        alpha = ParseTokenAsFloat(GetRequiredToken(*Alphas,0));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
LayeredTexture::~LayeredTexture()
 | 
			
		||||
{
 | 
			
		||||
    
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void LayeredTexture::fillTexture(const Document& doc)
 | 
			
		||||
{
 | 
			
		||||
    const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID());
 | 
			
		||||
    for(size_t i = 0; i < conns.size();++i)
 | 
			
		||||
    {
 | 
			
		||||
        const Connection* con = conns.at(i);
 | 
			
		||||
 | 
			
		||||
        const Object* const ob = con->SourceObject();
 | 
			
		||||
        if(!ob) {
 | 
			
		||||
            DOMWarning("failed to read source object for texture link, ignoring",&element);
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const Texture* const tex = dynamic_cast<const Texture*>(ob);
 | 
			
		||||
 | 
			
		||||
        textures.push_back(tex);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
Video::Video(uint64_t id, const Element& element, const Document& doc, const std::string& name)
 | 
			
		||||
: Object(id,element,name)
 | 
			
		||||
, contentLength(0)
 | 
			
		||||
, content(0)
 | 
			
		||||
{
 | 
			
		||||
    const Scope& sc = GetRequiredScope(element);
 | 
			
		||||
 | 
			
		||||
    const Element* const Type = sc["Type"];
 | 
			
		||||
    const Element* const FileName = sc.FindElementCaseInsensitive("FileName");  //some files retain the information as "Filename", others "FileName", who knows
 | 
			
		||||
    const Element* const RelativeFilename = sc["RelativeFilename"];
 | 
			
		||||
    const Element* const Content = sc["Content"];
 | 
			
		||||
 | 
			
		||||
    if(Type) {
 | 
			
		||||
        type = ParseTokenAsString(GetRequiredToken(*Type,0));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(FileName) {
 | 
			
		||||
        fileName = ParseTokenAsString(GetRequiredToken(*FileName,0));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(RelativeFilename) {
 | 
			
		||||
        relativeFileName = ParseTokenAsString(GetRequiredToken(*RelativeFilename,0));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(Content && !Content->Tokens().empty()) {
 | 
			
		||||
        //this field is omitted when the embedded texture is already loaded, let's ignore if it's not found
 | 
			
		||||
        try {
 | 
			
		||||
            const Token& token = GetRequiredToken(*Content, 0);
 | 
			
		||||
            const char* data = token.begin();
 | 
			
		||||
            if (!token.IsBinary()) {
 | 
			
		||||
                if (*data != '"') {
 | 
			
		||||
                    DOMError("embedded content is not surrounded by quotation marks", &element);
 | 
			
		||||
                }
 | 
			
		||||
                else {
 | 
			
		||||
                    size_t targetLength = 0;
 | 
			
		||||
                    auto numTokens = Content->Tokens().size();
 | 
			
		||||
                    // First time compute size (it could be large like 64Gb and it is good to allocate it once)
 | 
			
		||||
                    for (uint32_t tokenIdx = 0; tokenIdx < numTokens; ++tokenIdx)
 | 
			
		||||
                    {
 | 
			
		||||
                        const Token& dataToken = GetRequiredToken(*Content, tokenIdx);
 | 
			
		||||
                        size_t tokenLength = dataToken.end() - dataToken.begin() - 2; // ignore double quotes
 | 
			
		||||
                        const char* base64data = dataToken.begin() + 1;
 | 
			
		||||
                        const size_t outLength = Util::ComputeDecodedSizeBase64(base64data, tokenLength);
 | 
			
		||||
                        if (outLength == 0)
 | 
			
		||||
                        {
 | 
			
		||||
                            DOMError("Corrupted embedded content found", &element);
 | 
			
		||||
                        }
 | 
			
		||||
                        targetLength += outLength;
 | 
			
		||||
                    }
 | 
			
		||||
                    if (targetLength == 0)
 | 
			
		||||
                    {
 | 
			
		||||
                        DOMError("Corrupted embedded content found", &element);
 | 
			
		||||
                    }
 | 
			
		||||
                    content = new uint8_t[targetLength];
 | 
			
		||||
                    contentLength = static_cast<uint64_t>(targetLength);
 | 
			
		||||
                    size_t dst_offset = 0;
 | 
			
		||||
                    for (uint32_t tokenIdx = 0; tokenIdx < numTokens; ++tokenIdx)
 | 
			
		||||
                    {
 | 
			
		||||
                        const Token& dataToken = GetRequiredToken(*Content, tokenIdx);
 | 
			
		||||
                        size_t tokenLength = dataToken.end() - dataToken.begin() - 2; // ignore double quotes
 | 
			
		||||
                        const char* base64data = dataToken.begin() + 1;
 | 
			
		||||
                        dst_offset += Util::DecodeBase64(base64data, tokenLength, content + dst_offset, targetLength - dst_offset);
 | 
			
		||||
                    }
 | 
			
		||||
                    if (targetLength != dst_offset)
 | 
			
		||||
                    {
 | 
			
		||||
                        delete[] content;
 | 
			
		||||
                        contentLength = 0;
 | 
			
		||||
                        DOMError("Corrupted embedded content found", &element);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            else if (static_cast<size_t>(token.end() - data) < 5) {
 | 
			
		||||
                DOMError("binary data array is too short, need five (5) bytes for type signature and element count", &element);
 | 
			
		||||
            }
 | 
			
		||||
            else if (*data != 'R') {
 | 
			
		||||
                DOMWarning("video content is not raw binary data, ignoring", &element);
 | 
			
		||||
            }
 | 
			
		||||
            else {
 | 
			
		||||
                // read number of elements
 | 
			
		||||
                uint32_t len = 0;
 | 
			
		||||
                ::memcpy(&len, data + 1, sizeof(len));
 | 
			
		||||
                AI_SWAP4(len);
 | 
			
		||||
 | 
			
		||||
                contentLength = len;
 | 
			
		||||
 | 
			
		||||
                content = new uint8_t[len];
 | 
			
		||||
                ::memcpy(content, data + 5, len);
 | 
			
		||||
            }
 | 
			
		||||
        } catch (const runtime_error& runtimeError)
 | 
			
		||||
        {
 | 
			
		||||
            //we don't need the content data for contents that has already been loaded
 | 
			
		||||
            ASSIMP_LOG_DEBUG_F("Caught exception in FBXMaterial (likely because content was already loaded): ",
 | 
			
		||||
                    runtimeError.what());
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    props = GetPropertyTable(doc,"Video.FbxVideo",element,sc);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Video::~Video()
 | 
			
		||||
{
 | 
			
		||||
    if(content) {
 | 
			
		||||
        delete[] content;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} //!FBX
 | 
			
		||||
} //!Assimp
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										709
									
								
								thirdparty/assimp/code/FBX/FBXMeshGeometry.cpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										709
									
								
								thirdparty/assimp/code/FBX/FBXMeshGeometry.cpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,709 @@
 | 
			
		||||
/*
 | 
			
		||||
Open Asset Import Library (assimp)
 | 
			
		||||
----------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
Copyright (c) 2006-2019, 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  FBXMeshGeometry.cpp
 | 
			
		||||
 *  @brief Assimp::FBX::MeshGeometry implementation
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef ASSIMP_BUILD_NO_FBX_IMPORTER
 | 
			
		||||
 | 
			
		||||
#include <functional>
 | 
			
		||||
 | 
			
		||||
#include "FBXMeshGeometry.h"
 | 
			
		||||
#include "FBXDocument.h"
 | 
			
		||||
#include "FBXImporter.h"
 | 
			
		||||
#include "FBXImportSettings.h"
 | 
			
		||||
#include "FBXDocumentUtil.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
namespace Assimp {
 | 
			
		||||
namespace FBX {
 | 
			
		||||
 | 
			
		||||
using namespace Util;
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
Geometry::Geometry(uint64_t id, const Element& element, const std::string& name, const Document& doc)
 | 
			
		||||
    : Object(id, element, name)
 | 
			
		||||
    , skin()
 | 
			
		||||
{
 | 
			
		||||
    const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID(),"Deformer");
 | 
			
		||||
    for(const Connection* con : conns) {
 | 
			
		||||
        const Skin* const sk = ProcessSimpleConnection<Skin>(*con, false, "Skin -> Geometry", element);
 | 
			
		||||
        if(sk) {
 | 
			
		||||
            skin = sk;
 | 
			
		||||
        }
 | 
			
		||||
        const BlendShape* const bsp = ProcessSimpleConnection<BlendShape>(*con, false, "BlendShape -> Geometry", element);
 | 
			
		||||
        if (bsp) {
 | 
			
		||||
            blendShapes.push_back(bsp);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
Geometry::~Geometry()
 | 
			
		||||
{
 | 
			
		||||
    // empty
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
const std::vector<const BlendShape*>& Geometry::GetBlendShapes() const {
 | 
			
		||||
    return blendShapes;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
const Skin* Geometry::DeformerSkin() const {
 | 
			
		||||
    return skin;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
MeshGeometry::MeshGeometry(uint64_t id, const Element& element, const std::string& name, const Document& doc)
 | 
			
		||||
: Geometry(id, element,name, doc)
 | 
			
		||||
{
 | 
			
		||||
    const Scope* sc = element.Compound();
 | 
			
		||||
    if (!sc) {
 | 
			
		||||
        DOMError("failed to read Geometry object (class: Mesh), no data scope found");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // must have Mesh elements:
 | 
			
		||||
    const Element& Vertices = GetRequiredElement(*sc,"Vertices",&element);
 | 
			
		||||
    const Element& PolygonVertexIndex = GetRequiredElement(*sc,"PolygonVertexIndex",&element);
 | 
			
		||||
 | 
			
		||||
    // optional Mesh elements:
 | 
			
		||||
    const ElementCollection& Layer = sc->GetCollection("Layer");
 | 
			
		||||
 | 
			
		||||
    std::vector<aiVector3D> tempVerts;
 | 
			
		||||
    ParseVectorDataArray(tempVerts,Vertices);
 | 
			
		||||
 | 
			
		||||
    if(tempVerts.empty()) {
 | 
			
		||||
        FBXImporter::LogWarn("encountered mesh with no vertices");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::vector<int> tempFaces;
 | 
			
		||||
    ParseVectorDataArray(tempFaces,PolygonVertexIndex);
 | 
			
		||||
 | 
			
		||||
    if(tempFaces.empty()) {
 | 
			
		||||
        FBXImporter::LogWarn("encountered mesh with no faces");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    m_vertices.reserve(tempFaces.size());
 | 
			
		||||
    m_faces.reserve(tempFaces.size() / 3);
 | 
			
		||||
 | 
			
		||||
    m_mapping_offsets.resize(tempVerts.size());
 | 
			
		||||
    m_mapping_counts.resize(tempVerts.size(),0);
 | 
			
		||||
    m_mappings.resize(tempFaces.size());
 | 
			
		||||
 | 
			
		||||
    const size_t vertex_count = tempVerts.size();
 | 
			
		||||
 | 
			
		||||
    // generate output vertices, computing an adjacency table to
 | 
			
		||||
    // preserve the mapping from fbx indices to *this* indexing.
 | 
			
		||||
    unsigned int count = 0;
 | 
			
		||||
    for(int index : tempFaces) {
 | 
			
		||||
        const int absi = index < 0 ? (-index - 1) : index;
 | 
			
		||||
        if(static_cast<size_t>(absi) >= vertex_count) {
 | 
			
		||||
            DOMError("polygon vertex index out of range",&PolygonVertexIndex);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        m_vertices.push_back(tempVerts[absi]);
 | 
			
		||||
        ++count;
 | 
			
		||||
 | 
			
		||||
        ++m_mapping_counts[absi];
 | 
			
		||||
 | 
			
		||||
        if (index < 0) {
 | 
			
		||||
            m_faces.push_back(count);
 | 
			
		||||
            count = 0;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    unsigned int cursor = 0;
 | 
			
		||||
    for (size_t i = 0, e = tempVerts.size(); i < e; ++i) {
 | 
			
		||||
        m_mapping_offsets[i] = cursor;
 | 
			
		||||
        cursor += m_mapping_counts[i];
 | 
			
		||||
 | 
			
		||||
        m_mapping_counts[i] = 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    cursor = 0;
 | 
			
		||||
    for(int index : tempFaces) {
 | 
			
		||||
        const int absi = index < 0 ? (-index - 1) : index;
 | 
			
		||||
        m_mappings[m_mapping_offsets[absi] + m_mapping_counts[absi]++] = cursor++;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // if settings.readAllLayers is true:
 | 
			
		||||
    //  * read all layers, try to load as many vertex channels as possible
 | 
			
		||||
    // if settings.readAllLayers is false:
 | 
			
		||||
    //  * read only the layer with index 0, but warn about any further layers
 | 
			
		||||
    for (ElementMap::const_iterator it = Layer.first; it != Layer.second; ++it) {
 | 
			
		||||
        const TokenList& tokens = (*it).second->Tokens();
 | 
			
		||||
 | 
			
		||||
        const char* err;
 | 
			
		||||
        const int index = ParseTokenAsInt(*tokens[0], err);
 | 
			
		||||
        if(err) {
 | 
			
		||||
            DOMError(err,&element);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if(doc.Settings().readAllLayers || index == 0) {
 | 
			
		||||
            const Scope& layer = GetRequiredScope(*(*it).second);
 | 
			
		||||
            ReadLayer(layer);
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
            FBXImporter::LogWarn("ignoring additional geometry layers");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
MeshGeometry::~MeshGeometry() {
 | 
			
		||||
    // empty
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
const std::vector<aiVector3D>& MeshGeometry::GetVertices() const {
 | 
			
		||||
    return m_vertices;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
const std::vector<aiVector3D>& MeshGeometry::GetNormals() const {
 | 
			
		||||
    return m_normals;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
const std::vector<aiVector3D>& MeshGeometry::GetTangents() const {
 | 
			
		||||
    return m_tangents;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
const std::vector<aiVector3D>& MeshGeometry::GetBinormals() const {
 | 
			
		||||
    return m_binormals;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
const std::vector<unsigned int>& MeshGeometry::GetFaceIndexCounts() const {
 | 
			
		||||
    return m_faces;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
const std::vector<aiVector2D>& MeshGeometry::GetTextureCoords( unsigned int index ) const {
 | 
			
		||||
    static const std::vector<aiVector2D> empty;
 | 
			
		||||
    return index >= AI_MAX_NUMBER_OF_TEXTURECOORDS ? empty : m_uvs[ index ];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::string MeshGeometry::GetTextureCoordChannelName( unsigned int index ) const {
 | 
			
		||||
    return index >= AI_MAX_NUMBER_OF_TEXTURECOORDS ? "" : m_uvNames[ index ];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const std::vector<aiColor4D>& MeshGeometry::GetVertexColors( unsigned int index ) const {
 | 
			
		||||
    static const std::vector<aiColor4D> empty;
 | 
			
		||||
    return index >= AI_MAX_NUMBER_OF_COLOR_SETS ? empty : m_colors[ index ];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const MatIndexArray& MeshGeometry::GetMaterialIndices() const {
 | 
			
		||||
    return m_materials;
 | 
			
		||||
}
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
const unsigned int* MeshGeometry::ToOutputVertexIndex( unsigned int in_index, unsigned int& count ) const {
 | 
			
		||||
    if ( in_index >= m_mapping_counts.size() ) {
 | 
			
		||||
        return NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ai_assert( m_mapping_counts.size() == m_mapping_offsets.size() );
 | 
			
		||||
    count = m_mapping_counts[ in_index ];
 | 
			
		||||
 | 
			
		||||
    ai_assert( m_mapping_offsets[ in_index ] + count <= m_mappings.size() );
 | 
			
		||||
 | 
			
		||||
    return &m_mappings[ m_mapping_offsets[ in_index ] ];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
unsigned int MeshGeometry::FaceForVertexIndex( unsigned int in_index ) const {
 | 
			
		||||
    ai_assert( in_index < m_vertices.size() );
 | 
			
		||||
 | 
			
		||||
    // in the current conversion pattern this will only be needed if
 | 
			
		||||
    // weights are present, so no need to always pre-compute this table
 | 
			
		||||
    if ( m_facesVertexStartIndices.empty() ) {
 | 
			
		||||
        m_facesVertexStartIndices.resize( m_faces.size() + 1, 0 );
 | 
			
		||||
 | 
			
		||||
        std::partial_sum( m_faces.begin(), m_faces.end(), m_facesVertexStartIndices.begin() + 1 );
 | 
			
		||||
        m_facesVertexStartIndices.pop_back();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ai_assert( m_facesVertexStartIndices.size() == m_faces.size() );
 | 
			
		||||
    const std::vector<unsigned int>::iterator it = std::upper_bound(
 | 
			
		||||
        m_facesVertexStartIndices.begin(),
 | 
			
		||||
        m_facesVertexStartIndices.end(),
 | 
			
		||||
        in_index
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
    return static_cast< unsigned int >( std::distance( m_facesVertexStartIndices.begin(), it - 1 ) );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
void MeshGeometry::ReadLayer(const Scope& layer)
 | 
			
		||||
{
 | 
			
		||||
    const ElementCollection& LayerElement = layer.GetCollection("LayerElement");
 | 
			
		||||
    for (ElementMap::const_iterator eit = LayerElement.first; eit != LayerElement.second; ++eit) {
 | 
			
		||||
        const Scope& elayer = GetRequiredScope(*(*eit).second);
 | 
			
		||||
 | 
			
		||||
        ReadLayerElement(elayer);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
void MeshGeometry::ReadLayerElement(const Scope& layerElement)
 | 
			
		||||
{
 | 
			
		||||
    const Element& Type = GetRequiredElement(layerElement,"Type");
 | 
			
		||||
    const Element& TypedIndex = GetRequiredElement(layerElement,"TypedIndex");
 | 
			
		||||
 | 
			
		||||
    const std::string& type = ParseTokenAsString(GetRequiredToken(Type,0));
 | 
			
		||||
    const int typedIndex = ParseTokenAsInt(GetRequiredToken(TypedIndex,0));
 | 
			
		||||
 | 
			
		||||
    const Scope& top = GetRequiredScope(element);
 | 
			
		||||
    const ElementCollection candidates = top.GetCollection(type);
 | 
			
		||||
 | 
			
		||||
    for (ElementMap::const_iterator it = candidates.first; it != candidates.second; ++it) {
 | 
			
		||||
        const int index = ParseTokenAsInt(GetRequiredToken(*(*it).second,0));
 | 
			
		||||
        if(index == typedIndex) {
 | 
			
		||||
            ReadVertexData(type,typedIndex,GetRequiredScope(*(*it).second));
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    FBXImporter::LogError(Formatter::format("failed to resolve vertex layer element: ")
 | 
			
		||||
        << type << ", index: " << typedIndex);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
void MeshGeometry::ReadVertexData(const std::string& type, int index, const Scope& source)
 | 
			
		||||
{
 | 
			
		||||
    const std::string& MappingInformationType = ParseTokenAsString(GetRequiredToken(
 | 
			
		||||
        GetRequiredElement(source,"MappingInformationType"),0)
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    const std::string& ReferenceInformationType = ParseTokenAsString(GetRequiredToken(
 | 
			
		||||
        GetRequiredElement(source,"ReferenceInformationType"),0)
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    if (type == "LayerElementUV") {
 | 
			
		||||
        if(index >= AI_MAX_NUMBER_OF_TEXTURECOORDS) {
 | 
			
		||||
            FBXImporter::LogError(Formatter::format("ignoring UV layer, maximum number of UV channels exceeded: ")
 | 
			
		||||
                << index << " (limit is " << AI_MAX_NUMBER_OF_TEXTURECOORDS << ")" );
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const Element* Name = source["Name"];
 | 
			
		||||
        m_uvNames[index] = "";
 | 
			
		||||
        if(Name) {
 | 
			
		||||
            m_uvNames[index] = ParseTokenAsString(GetRequiredToken(*Name,0));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        ReadVertexDataUV(m_uvs[index],source,
 | 
			
		||||
            MappingInformationType,
 | 
			
		||||
            ReferenceInformationType
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
    else if (type == "LayerElementMaterial") {
 | 
			
		||||
        if (m_materials.size() > 0) {
 | 
			
		||||
            FBXImporter::LogError("ignoring additional material layer");
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        std::vector<int> temp_materials;
 | 
			
		||||
 | 
			
		||||
        ReadVertexDataMaterials(temp_materials,source,
 | 
			
		||||
            MappingInformationType,
 | 
			
		||||
            ReferenceInformationType
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        // sometimes, there will be only negative entries. Drop the material
 | 
			
		||||
        // layer in such a case (I guess it means a default material should
 | 
			
		||||
        // be used). This is what the converter would do anyway, and it
 | 
			
		||||
        // avoids losing the material if there are more material layers
 | 
			
		||||
        // coming of which at least one contains actual data (did observe
 | 
			
		||||
        // that with one test file).
 | 
			
		||||
        const size_t count_neg = std::count_if(temp_materials.begin(),temp_materials.end(),[](int n) { return n < 0; });
 | 
			
		||||
        if(count_neg == temp_materials.size()) {
 | 
			
		||||
            FBXImporter::LogWarn("ignoring dummy material layer (all entries -1)");
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        std::swap(temp_materials, m_materials);
 | 
			
		||||
    }
 | 
			
		||||
    else if (type == "LayerElementNormal") {
 | 
			
		||||
        if (m_normals.size() > 0) {
 | 
			
		||||
            FBXImporter::LogError("ignoring additional normal layer");
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        ReadVertexDataNormals(m_normals,source,
 | 
			
		||||
            MappingInformationType,
 | 
			
		||||
            ReferenceInformationType
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
    else if (type == "LayerElementTangent") {
 | 
			
		||||
        if (m_tangents.size() > 0) {
 | 
			
		||||
            FBXImporter::LogError("ignoring additional tangent layer");
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        ReadVertexDataTangents(m_tangents,source,
 | 
			
		||||
            MappingInformationType,
 | 
			
		||||
            ReferenceInformationType
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
    else if (type == "LayerElementBinormal") {
 | 
			
		||||
        if (m_binormals.size() > 0) {
 | 
			
		||||
            FBXImporter::LogError("ignoring additional binormal layer");
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        ReadVertexDataBinormals(m_binormals,source,
 | 
			
		||||
            MappingInformationType,
 | 
			
		||||
            ReferenceInformationType
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
    else if (type == "LayerElementColor") {
 | 
			
		||||
        if(index >= AI_MAX_NUMBER_OF_COLOR_SETS) {
 | 
			
		||||
            FBXImporter::LogError(Formatter::format("ignoring vertex color layer, maximum number of color sets exceeded: ")
 | 
			
		||||
                << index << " (limit is " << AI_MAX_NUMBER_OF_COLOR_SETS << ")" );
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        ReadVertexDataColors(m_colors[index],source,
 | 
			
		||||
            MappingInformationType,
 | 
			
		||||
            ReferenceInformationType
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
// Lengthy utility function to read and resolve a FBX vertex data array - that is, the
 | 
			
		||||
// output is in polygon vertex order. This logic is used for reading normals, UVs, colors,
 | 
			
		||||
// tangents ..
 | 
			
		||||
template <typename T>
 | 
			
		||||
void ResolveVertexDataArray(std::vector<T>& data_out, const Scope& source,
 | 
			
		||||
    const std::string& MappingInformationType,
 | 
			
		||||
    const std::string& ReferenceInformationType,
 | 
			
		||||
    const char* dataElementName,
 | 
			
		||||
    const char* indexDataElementName,
 | 
			
		||||
    size_t vertex_count,
 | 
			
		||||
    const std::vector<unsigned int>& mapping_counts,
 | 
			
		||||
    const std::vector<unsigned int>& mapping_offsets,
 | 
			
		||||
    const std::vector<unsigned int>& mappings)
 | 
			
		||||
{
 | 
			
		||||
    bool isDirect = ReferenceInformationType == "Direct";
 | 
			
		||||
    bool isIndexToDirect = ReferenceInformationType == "IndexToDirect";
 | 
			
		||||
 | 
			
		||||
    // fall-back to direct data if there is no index data element
 | 
			
		||||
    if ( isIndexToDirect && !HasElement( source, indexDataElementName ) ) {
 | 
			
		||||
        isDirect = true;
 | 
			
		||||
        isIndexToDirect = false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // handle permutations of Mapping and Reference type - it would be nice to
 | 
			
		||||
    // deal with this more elegantly and with less redundancy, but right
 | 
			
		||||
    // now it seems unavoidable.
 | 
			
		||||
    if (MappingInformationType == "ByVertice" && isDirect) {
 | 
			
		||||
        if (!HasElement(source, dataElementName)) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        std::vector<T> tempData;
 | 
			
		||||
		ParseVectorDataArray(tempData, GetRequiredElement(source, dataElementName));
 | 
			
		||||
 | 
			
		||||
        data_out.resize(vertex_count);
 | 
			
		||||
		for (size_t i = 0, e = tempData.size(); i < e; ++i) {
 | 
			
		||||
 | 
			
		||||
            const unsigned int istart = mapping_offsets[i], iend = istart + mapping_counts[i];
 | 
			
		||||
            for (unsigned int j = istart; j < iend; ++j) {
 | 
			
		||||
				data_out[mappings[j]] = tempData[i];
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    else if (MappingInformationType == "ByVertice" && isIndexToDirect) {
 | 
			
		||||
		std::vector<T> tempData;
 | 
			
		||||
		ParseVectorDataArray(tempData, GetRequiredElement(source, dataElementName));
 | 
			
		||||
 | 
			
		||||
        data_out.resize(vertex_count);
 | 
			
		||||
 | 
			
		||||
        std::vector<int> uvIndices;
 | 
			
		||||
        ParseVectorDataArray(uvIndices,GetRequiredElement(source,indexDataElementName));
 | 
			
		||||
        for (size_t i = 0, e = uvIndices.size(); i < e; ++i) {
 | 
			
		||||
 | 
			
		||||
            const unsigned int istart = mapping_offsets[i], iend = istart + mapping_counts[i];
 | 
			
		||||
            for (unsigned int j = istart; j < iend; ++j) {
 | 
			
		||||
				if (static_cast<size_t>(uvIndices[i]) >= tempData.size()) {
 | 
			
		||||
                    DOMError("index out of range",&GetRequiredElement(source,indexDataElementName));
 | 
			
		||||
                }
 | 
			
		||||
				data_out[mappings[j]] = tempData[uvIndices[i]];
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    else if (MappingInformationType == "ByPolygonVertex" && isDirect) {
 | 
			
		||||
		std::vector<T> tempData;
 | 
			
		||||
		ParseVectorDataArray(tempData, GetRequiredElement(source, dataElementName));
 | 
			
		||||
 | 
			
		||||
		if (tempData.size() != vertex_count) {
 | 
			
		||||
            FBXImporter::LogError(Formatter::format("length of input data unexpected for ByPolygon mapping: ")
 | 
			
		||||
				<< tempData.size() << ", expected " << vertex_count
 | 
			
		||||
            );
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
		data_out.swap(tempData);
 | 
			
		||||
    }
 | 
			
		||||
    else if (MappingInformationType == "ByPolygonVertex" && isIndexToDirect) {
 | 
			
		||||
		std::vector<T> tempData;
 | 
			
		||||
		ParseVectorDataArray(tempData, GetRequiredElement(source, dataElementName));
 | 
			
		||||
 | 
			
		||||
        data_out.resize(vertex_count);
 | 
			
		||||
 | 
			
		||||
        std::vector<int> uvIndices;
 | 
			
		||||
        ParseVectorDataArray(uvIndices,GetRequiredElement(source,indexDataElementName));
 | 
			
		||||
 | 
			
		||||
        if (uvIndices.size() != vertex_count) {
 | 
			
		||||
            FBXImporter::LogError("length of input data unexpected for ByPolygonVertex mapping");
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const T empty;
 | 
			
		||||
        unsigned int next = 0;
 | 
			
		||||
        for(int i : uvIndices) {
 | 
			
		||||
            if ( -1 == i ) {
 | 
			
		||||
                data_out[ next++ ] = empty;
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
            if (static_cast<size_t>(i) >= tempData.size()) {
 | 
			
		||||
                DOMError("index out of range",&GetRequiredElement(source,indexDataElementName));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
			data_out[next++] = tempData[i];
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
        FBXImporter::LogError(Formatter::format("ignoring vertex data channel, access type not implemented: ")
 | 
			
		||||
            << MappingInformationType << "," << ReferenceInformationType);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
void MeshGeometry::ReadVertexDataNormals(std::vector<aiVector3D>& normals_out, const Scope& source,
 | 
			
		||||
    const std::string& MappingInformationType,
 | 
			
		||||
    const std::string& ReferenceInformationType)
 | 
			
		||||
{
 | 
			
		||||
    ResolveVertexDataArray(normals_out,source,MappingInformationType,ReferenceInformationType,
 | 
			
		||||
        "Normals",
 | 
			
		||||
        "NormalsIndex",
 | 
			
		||||
        m_vertices.size(),
 | 
			
		||||
        m_mapping_counts,
 | 
			
		||||
        m_mapping_offsets,
 | 
			
		||||
        m_mappings);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
void MeshGeometry::ReadVertexDataUV(std::vector<aiVector2D>& uv_out, const Scope& source,
 | 
			
		||||
    const std::string& MappingInformationType,
 | 
			
		||||
    const std::string& ReferenceInformationType)
 | 
			
		||||
{
 | 
			
		||||
    ResolveVertexDataArray(uv_out,source,MappingInformationType,ReferenceInformationType,
 | 
			
		||||
        "UV",
 | 
			
		||||
        "UVIndex",
 | 
			
		||||
        m_vertices.size(),
 | 
			
		||||
        m_mapping_counts,
 | 
			
		||||
        m_mapping_offsets,
 | 
			
		||||
        m_mappings);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
void MeshGeometry::ReadVertexDataColors(std::vector<aiColor4D>& colors_out, const Scope& source,
 | 
			
		||||
    const std::string& MappingInformationType,
 | 
			
		||||
    const std::string& ReferenceInformationType)
 | 
			
		||||
{
 | 
			
		||||
    ResolveVertexDataArray(colors_out,source,MappingInformationType,ReferenceInformationType,
 | 
			
		||||
        "Colors",
 | 
			
		||||
        "ColorIndex",
 | 
			
		||||
        m_vertices.size(),
 | 
			
		||||
        m_mapping_counts,
 | 
			
		||||
        m_mapping_offsets,
 | 
			
		||||
        m_mappings);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
static const char *TangentIndexToken = "TangentIndex";
 | 
			
		||||
static const char *TangentsIndexToken = "TangentsIndex";
 | 
			
		||||
 | 
			
		||||
void MeshGeometry::ReadVertexDataTangents(std::vector<aiVector3D>& tangents_out, const Scope& source,
 | 
			
		||||
    const std::string& MappingInformationType,
 | 
			
		||||
    const std::string& ReferenceInformationType)
 | 
			
		||||
{
 | 
			
		||||
    const char * str = source.Elements().count( "Tangents" ) > 0 ? "Tangents" : "Tangent";
 | 
			
		||||
    const char * strIdx = source.Elements().count( "Tangents" ) > 0 ? TangentsIndexToken : TangentIndexToken;
 | 
			
		||||
    ResolveVertexDataArray(tangents_out,source,MappingInformationType,ReferenceInformationType,
 | 
			
		||||
        str,
 | 
			
		||||
        strIdx,
 | 
			
		||||
        m_vertices.size(),
 | 
			
		||||
        m_mapping_counts,
 | 
			
		||||
        m_mapping_offsets,
 | 
			
		||||
        m_mappings);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
static const std::string BinormalIndexToken = "BinormalIndex";
 | 
			
		||||
static const std::string BinormalsIndexToken = "BinormalsIndex";
 | 
			
		||||
 | 
			
		||||
void MeshGeometry::ReadVertexDataBinormals(std::vector<aiVector3D>& binormals_out, const Scope& source,
 | 
			
		||||
    const std::string& MappingInformationType,
 | 
			
		||||
    const std::string& ReferenceInformationType)
 | 
			
		||||
{
 | 
			
		||||
    const char * str = source.Elements().count( "Binormals" ) > 0 ? "Binormals" : "Binormal";
 | 
			
		||||
    const char * strIdx = source.Elements().count( "Binormals" ) > 0 ? BinormalsIndexToken.c_str() : BinormalIndexToken.c_str();
 | 
			
		||||
    ResolveVertexDataArray(binormals_out,source,MappingInformationType,ReferenceInformationType,
 | 
			
		||||
        str,
 | 
			
		||||
        strIdx,
 | 
			
		||||
        m_vertices.size(),
 | 
			
		||||
        m_mapping_counts,
 | 
			
		||||
        m_mapping_offsets,
 | 
			
		||||
        m_mappings);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
void MeshGeometry::ReadVertexDataMaterials(std::vector<int>& materials_out, const Scope& source,
 | 
			
		||||
    const std::string& MappingInformationType,
 | 
			
		||||
    const std::string& ReferenceInformationType)
 | 
			
		||||
{
 | 
			
		||||
    const size_t face_count = m_faces.size();
 | 
			
		||||
    if( 0 == face_count )
 | 
			
		||||
    {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // materials are handled separately. First of all, they are assigned per-face
 | 
			
		||||
    // and not per polyvert. Secondly, ReferenceInformationType=IndexToDirect
 | 
			
		||||
    // has a slightly different meaning for materials.
 | 
			
		||||
    ParseVectorDataArray(materials_out,GetRequiredElement(source,"Materials"));
 | 
			
		||||
 | 
			
		||||
    if (MappingInformationType == "AllSame") {
 | 
			
		||||
        // easy - same material for all faces
 | 
			
		||||
        if (materials_out.empty()) {
 | 
			
		||||
            FBXImporter::LogError(Formatter::format("expected material index, ignoring"));
 | 
			
		||||
            return;
 | 
			
		||||
        } else if (materials_out.size() > 1) {
 | 
			
		||||
            FBXImporter::LogWarn(Formatter::format("expected only a single material index, ignoring all except the first one"));
 | 
			
		||||
            materials_out.clear();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        materials_out.resize(m_vertices.size());
 | 
			
		||||
        std::fill(materials_out.begin(), materials_out.end(), materials_out.at(0));
 | 
			
		||||
    } else if (MappingInformationType == "ByPolygon" && ReferenceInformationType == "IndexToDirect") {
 | 
			
		||||
        materials_out.resize(face_count);
 | 
			
		||||
 | 
			
		||||
        if(materials_out.size() != face_count) {
 | 
			
		||||
            FBXImporter::LogError(Formatter::format("length of input data unexpected for ByPolygon mapping: ")
 | 
			
		||||
                << materials_out.size() << ", expected " << face_count
 | 
			
		||||
            );
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
        FBXImporter::LogError(Formatter::format("ignoring material assignments, access type not implemented: ")
 | 
			
		||||
            << MappingInformationType << "," << ReferenceInformationType);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
ShapeGeometry::ShapeGeometry(uint64_t id, const Element& element, const std::string& name, const Document& doc)
 | 
			
		||||
: Geometry(id, element, name, doc) {
 | 
			
		||||
    const Scope *sc = element.Compound();
 | 
			
		||||
    if (nullptr == sc) {
 | 
			
		||||
        DOMError("failed to read Geometry object (class: Shape), no data scope found");
 | 
			
		||||
    }
 | 
			
		||||
    const Element& Indexes = GetRequiredElement(*sc, "Indexes", &element);
 | 
			
		||||
    const Element& Normals = GetRequiredElement(*sc, "Normals", &element);
 | 
			
		||||
    const Element& Vertices = GetRequiredElement(*sc, "Vertices", &element);
 | 
			
		||||
    ParseVectorDataArray(m_indices, Indexes);
 | 
			
		||||
    ParseVectorDataArray(m_vertices, Vertices);
 | 
			
		||||
    ParseVectorDataArray(m_normals, Normals);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
ShapeGeometry::~ShapeGeometry() {
 | 
			
		||||
    // empty
 | 
			
		||||
}
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
const std::vector<aiVector3D>& ShapeGeometry::GetVertices() const {
 | 
			
		||||
    return m_vertices;
 | 
			
		||||
}
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
const std::vector<aiVector3D>& ShapeGeometry::GetNormals() const {
 | 
			
		||||
    return m_normals;
 | 
			
		||||
}
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
const std::vector<unsigned int>& ShapeGeometry::GetIndices() const {
 | 
			
		||||
    return m_indices;
 | 
			
		||||
}
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
LineGeometry::LineGeometry(uint64_t id, const Element& element, const std::string& name, const Document& doc)
 | 
			
		||||
    : Geometry(id, element, name, doc)
 | 
			
		||||
{
 | 
			
		||||
    const Scope* sc = element.Compound();
 | 
			
		||||
    if (!sc) {
 | 
			
		||||
        DOMError("failed to read Geometry object (class: Line), no data scope found");
 | 
			
		||||
    }
 | 
			
		||||
    const Element& Points = GetRequiredElement(*sc, "Points", &element);
 | 
			
		||||
    const Element& PointsIndex = GetRequiredElement(*sc, "PointsIndex", &element);
 | 
			
		||||
    ParseVectorDataArray(m_vertices, Points);
 | 
			
		||||
    ParseVectorDataArray(m_indices, PointsIndex);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
LineGeometry::~LineGeometry() {
 | 
			
		||||
    // empty
 | 
			
		||||
}
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
const std::vector<aiVector3D>& LineGeometry::GetVertices() const {
 | 
			
		||||
    return m_vertices;
 | 
			
		||||
}
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
const std::vector<int>& LineGeometry::GetIndices() const {
 | 
			
		||||
    return m_indices;
 | 
			
		||||
}
 | 
			
		||||
} // !FBX
 | 
			
		||||
} // !Assimp
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										235
									
								
								thirdparty/assimp/code/FBX/FBXMeshGeometry.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										235
									
								
								thirdparty/assimp/code/FBX/FBXMeshGeometry.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,235 @@
 | 
			
		||||
/*
 | 
			
		||||
Open Asset Import Library (assimp)
 | 
			
		||||
----------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
Copyright (c) 2006-2019, 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  FBXImporter.h
 | 
			
		||||
*  @brief Declaration of the FBX main importer class
 | 
			
		||||
*/
 | 
			
		||||
#ifndef INCLUDED_AI_FBX_MESHGEOMETRY_H
 | 
			
		||||
#define INCLUDED_AI_FBX_MESHGEOMETRY_H
 | 
			
		||||
 | 
			
		||||
#include "FBXParser.h"
 | 
			
		||||
#include "FBXDocument.h"
 | 
			
		||||
 | 
			
		||||
namespace Assimp {
 | 
			
		||||
namespace FBX {
 | 
			
		||||
 | 
			
		||||
/** 
 | 
			
		||||
 *  DOM base class for all kinds of FBX geometry 
 | 
			
		||||
 */
 | 
			
		||||
class Geometry : public Object
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    Geometry( uint64_t id, const Element& element, const std::string& name, const Document& doc );
 | 
			
		||||
    virtual ~Geometry();
 | 
			
		||||
 | 
			
		||||
    /** Get the Skin attached to this geometry or NULL */
 | 
			
		||||
    const Skin* DeformerSkin() const;
 | 
			
		||||
 | 
			
		||||
    /** Get the BlendShape attached to this geometry or NULL */
 | 
			
		||||
    const std::vector<const BlendShape*>& GetBlendShapes() const;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    const Skin* skin;
 | 
			
		||||
    std::vector<const BlendShape*> blendShapes;
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef std::vector<int> MatIndexArray;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/** 
 | 
			
		||||
 *  DOM class for FBX geometry of type "Mesh"
 | 
			
		||||
 */
 | 
			
		||||
class MeshGeometry : public Geometry
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    /** The class constructor */
 | 
			
		||||
    MeshGeometry( uint64_t id, const Element& element, const std::string& name, const Document& doc );
 | 
			
		||||
    
 | 
			
		||||
    /** The class destructor */
 | 
			
		||||
    virtual ~MeshGeometry();
 | 
			
		||||
 | 
			
		||||
    /** Get a list of all vertex points, non-unique*/
 | 
			
		||||
    const std::vector<aiVector3D>& GetVertices() const;
 | 
			
		||||
 | 
			
		||||
    /** Get a list of all vertex normals or an empty array if
 | 
			
		||||
    *  no normals are specified. */
 | 
			
		||||
    const std::vector<aiVector3D>& GetNormals() const;
 | 
			
		||||
 | 
			
		||||
    /** Get a list of all vertex tangents or an empty array
 | 
			
		||||
    *  if no tangents are specified */
 | 
			
		||||
    const std::vector<aiVector3D>& GetTangents() const;
 | 
			
		||||
 | 
			
		||||
    /** Get a list of all vertex bi-normals or an empty array
 | 
			
		||||
    *  if no bi-normals are specified */
 | 
			
		||||
    const std::vector<aiVector3D>& GetBinormals() const;
 | 
			
		||||
 | 
			
		||||
    /** Return list of faces - each entry denotes a face and specifies
 | 
			
		||||
    *  how many vertices it has. Vertices are taken from the
 | 
			
		||||
    *  vertex data arrays in sequential order. */
 | 
			
		||||
    const std::vector<unsigned int>& GetFaceIndexCounts() const;
 | 
			
		||||
 | 
			
		||||
    /** Get a UV coordinate slot, returns an empty array if
 | 
			
		||||
    *  the requested slot does not exist. */
 | 
			
		||||
    const std::vector<aiVector2D>& GetTextureCoords( unsigned int index ) const;
 | 
			
		||||
 | 
			
		||||
    /** Get a UV coordinate slot, returns an empty array if
 | 
			
		||||
    *  the requested slot does not exist. */
 | 
			
		||||
    std::string GetTextureCoordChannelName( unsigned int index ) const;
 | 
			
		||||
 | 
			
		||||
    /** Get a vertex color coordinate slot, returns an empty array if
 | 
			
		||||
    *  the requested slot does not exist. */
 | 
			
		||||
    const std::vector<aiColor4D>& GetVertexColors( unsigned int index ) const;
 | 
			
		||||
 | 
			
		||||
    /** Get per-face-vertex material assignments */
 | 
			
		||||
    const MatIndexArray& GetMaterialIndices() const;
 | 
			
		||||
 | 
			
		||||
    /** Convert from a fbx file vertex index (for example from a #Cluster weight) or NULL
 | 
			
		||||
    * if the vertex index is not valid. */
 | 
			
		||||
    const unsigned int* ToOutputVertexIndex( unsigned int in_index, unsigned int& count ) const;
 | 
			
		||||
 | 
			
		||||
    /** Determine the face to which a particular output vertex index belongs.
 | 
			
		||||
    *  This mapping is always unique. */
 | 
			
		||||
    unsigned int FaceForVertexIndex( unsigned int in_index ) const;
 | 
			
		||||
private:
 | 
			
		||||
    void ReadLayer( const Scope& layer );
 | 
			
		||||
    void ReadLayerElement( const Scope& layerElement );
 | 
			
		||||
    void ReadVertexData( const std::string& type, int index, const Scope& source );
 | 
			
		||||
 | 
			
		||||
    void ReadVertexDataUV( std::vector<aiVector2D>& uv_out, const Scope& source,
 | 
			
		||||
        const std::string& MappingInformationType,
 | 
			
		||||
        const std::string& ReferenceInformationType );
 | 
			
		||||
 | 
			
		||||
    void ReadVertexDataNormals( std::vector<aiVector3D>& normals_out, const Scope& source,
 | 
			
		||||
        const std::string& MappingInformationType,
 | 
			
		||||
        const std::string& ReferenceInformationType );
 | 
			
		||||
 | 
			
		||||
    void ReadVertexDataColors( std::vector<aiColor4D>& colors_out, const Scope& source,
 | 
			
		||||
        const std::string& MappingInformationType,
 | 
			
		||||
        const std::string& ReferenceInformationType );
 | 
			
		||||
 | 
			
		||||
    void ReadVertexDataTangents( std::vector<aiVector3D>& tangents_out, const Scope& source,
 | 
			
		||||
        const std::string& MappingInformationType,
 | 
			
		||||
        const std::string& ReferenceInformationType );
 | 
			
		||||
 | 
			
		||||
    void ReadVertexDataBinormals( std::vector<aiVector3D>& binormals_out, const Scope& source,
 | 
			
		||||
        const std::string& MappingInformationType,
 | 
			
		||||
        const std::string& ReferenceInformationType );
 | 
			
		||||
 | 
			
		||||
    void ReadVertexDataMaterials( MatIndexArray& materials_out, const Scope& source,
 | 
			
		||||
        const std::string& MappingInformationType,
 | 
			
		||||
        const std::string& ReferenceInformationType );
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    // cached data arrays
 | 
			
		||||
    MatIndexArray m_materials;
 | 
			
		||||
    std::vector<aiVector3D> m_vertices;
 | 
			
		||||
    std::vector<unsigned int> m_faces;
 | 
			
		||||
    mutable std::vector<unsigned int> m_facesVertexStartIndices;
 | 
			
		||||
    std::vector<aiVector3D> m_tangents;
 | 
			
		||||
    std::vector<aiVector3D> m_binormals;
 | 
			
		||||
    std::vector<aiVector3D> m_normals;
 | 
			
		||||
 | 
			
		||||
    std::string m_uvNames[ AI_MAX_NUMBER_OF_TEXTURECOORDS ];
 | 
			
		||||
    std::vector<aiVector2D> m_uvs[ AI_MAX_NUMBER_OF_TEXTURECOORDS ];
 | 
			
		||||
    std::vector<aiColor4D> m_colors[ AI_MAX_NUMBER_OF_COLOR_SETS ];
 | 
			
		||||
 | 
			
		||||
    std::vector<unsigned int> m_mapping_counts;
 | 
			
		||||
    std::vector<unsigned int> m_mapping_offsets;
 | 
			
		||||
    std::vector<unsigned int> m_mappings;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
*  DOM class for FBX geometry of type "Shape"
 | 
			
		||||
*/
 | 
			
		||||
class ShapeGeometry : public Geometry
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    /** The class constructor */
 | 
			
		||||
    ShapeGeometry(uint64_t id, const Element& element, const std::string& name, const Document& doc);
 | 
			
		||||
 | 
			
		||||
    /** The class destructor */
 | 
			
		||||
    virtual ~ShapeGeometry();
 | 
			
		||||
 | 
			
		||||
    /** Get a list of all vertex points, non-unique*/
 | 
			
		||||
    const std::vector<aiVector3D>& GetVertices() const;
 | 
			
		||||
 | 
			
		||||
    /** Get a list of all vertex normals or an empty array if
 | 
			
		||||
    *  no normals are specified. */
 | 
			
		||||
    const std::vector<aiVector3D>& GetNormals() const;
 | 
			
		||||
 | 
			
		||||
    /** Return list of vertex indices. */
 | 
			
		||||
    const std::vector<unsigned int>& GetIndices() const;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    std::vector<aiVector3D> m_vertices;
 | 
			
		||||
    std::vector<aiVector3D> m_normals;
 | 
			
		||||
    std::vector<unsigned int> m_indices;
 | 
			
		||||
};
 | 
			
		||||
/**
 | 
			
		||||
*  DOM class for FBX geometry of type "Line"
 | 
			
		||||
*/
 | 
			
		||||
class LineGeometry : public Geometry
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    /** The class constructor */
 | 
			
		||||
    LineGeometry(uint64_t id, const Element& element, const std::string& name, const Document& doc);
 | 
			
		||||
 | 
			
		||||
    /** The class destructor */
 | 
			
		||||
    virtual ~LineGeometry();
 | 
			
		||||
 | 
			
		||||
    /** Get a list of all vertex points, non-unique*/
 | 
			
		||||
    const std::vector<aiVector3D>& GetVertices() const;
 | 
			
		||||
 | 
			
		||||
    /** Return list of vertex indices. */
 | 
			
		||||
    const std::vector<int>& GetIndices() const;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    std::vector<aiVector3D> m_vertices;
 | 
			
		||||
    std::vector<int> m_indices;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif // INCLUDED_AI_FBX_MESHGEOMETRY_H
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										153
									
								
								thirdparty/assimp/code/FBX/FBXModel.cpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										153
									
								
								thirdparty/assimp/code/FBX/FBXModel.cpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,153 @@
 | 
			
		||||
/*
 | 
			
		||||
Open Asset Import Library (assimp)
 | 
			
		||||
----------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
Copyright (c) 2006-2019, 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  FBXModel.cpp
 | 
			
		||||
 *  @brief Assimp::FBX::Model implementation
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef ASSIMP_BUILD_NO_FBX_IMPORTER
 | 
			
		||||
 | 
			
		||||
#include "FBXParser.h"
 | 
			
		||||
#include "FBXMeshGeometry.h"
 | 
			
		||||
#include "FBXDocument.h"
 | 
			
		||||
#include "FBXImporter.h"
 | 
			
		||||
#include "FBXDocumentUtil.h"
 | 
			
		||||
 | 
			
		||||
namespace Assimp {
 | 
			
		||||
namespace FBX {
 | 
			
		||||
 | 
			
		||||
using namespace Util;
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
Model::Model(uint64_t id, const Element& element, const Document& doc, const std::string& name)
 | 
			
		||||
    : Object(id,element,name)
 | 
			
		||||
    , shading("Y")
 | 
			
		||||
{
 | 
			
		||||
    const Scope& sc = GetRequiredScope(element);
 | 
			
		||||
    const Element* const Shading = sc["Shading"];
 | 
			
		||||
    const Element* const Culling = sc["Culling"];
 | 
			
		||||
 | 
			
		||||
    if(Shading) {
 | 
			
		||||
        shading = GetRequiredToken(*Shading,0).StringContents();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (Culling) {
 | 
			
		||||
        culling = ParseTokenAsString(GetRequiredToken(*Culling,0));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    props = GetPropertyTable(doc,"Model.FbxNode",element,sc);
 | 
			
		||||
    ResolveLinks(element,doc);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
Model::~Model()
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
void Model::ResolveLinks(const Element& element, const Document& doc)
 | 
			
		||||
{
 | 
			
		||||
    const char* const arr[] = {"Geometry","Material","NodeAttribute"};
 | 
			
		||||
 | 
			
		||||
    // resolve material
 | 
			
		||||
    const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID(),arr, 3);
 | 
			
		||||
 | 
			
		||||
    materials.reserve(conns.size());
 | 
			
		||||
    geometry.reserve(conns.size());
 | 
			
		||||
    attributes.reserve(conns.size());
 | 
			
		||||
    for(const Connection* con : conns) {
 | 
			
		||||
 | 
			
		||||
        // material and geometry links should be Object-Object connections
 | 
			
		||||
        if (con->PropertyName().length()) {
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const Object* const ob = con->SourceObject();
 | 
			
		||||
        if(!ob) {
 | 
			
		||||
            DOMWarning("failed to read source object for incoming Model link, ignoring",&element);
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const Material* const mat = dynamic_cast<const Material*>(ob);
 | 
			
		||||
        if(mat) {
 | 
			
		||||
            materials.push_back(mat);
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const Geometry* const geo = dynamic_cast<const Geometry*>(ob);
 | 
			
		||||
        if(geo) {
 | 
			
		||||
            geometry.push_back(geo);
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const NodeAttribute* const att = dynamic_cast<const NodeAttribute*>(ob);
 | 
			
		||||
        if(att) {
 | 
			
		||||
            attributes.push_back(att);
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        DOMWarning("source object for model link is neither Material, NodeAttribute nor Geometry, ignoring",&element);
 | 
			
		||||
        continue;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
bool Model::IsNull() const
 | 
			
		||||
{
 | 
			
		||||
    const std::vector<const NodeAttribute*>& attrs = GetAttributes();
 | 
			
		||||
    for(const NodeAttribute* att : attrs) {
 | 
			
		||||
 | 
			
		||||
        const Null* null_tag = dynamic_cast<const Null*>(att);
 | 
			
		||||
        if(null_tag) {
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
} //!FBX
 | 
			
		||||
} //!Assimp
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										170
									
								
								thirdparty/assimp/code/FBX/FBXNodeAttribute.cpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										170
									
								
								thirdparty/assimp/code/FBX/FBXNodeAttribute.cpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,170 @@
 | 
			
		||||
/*
 | 
			
		||||
Open Asset Import Library (assimp)
 | 
			
		||||
----------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
Copyright (c) 2006-2019, 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  FBXNoteAttribute.cpp
 | 
			
		||||
 *  @brief Assimp::FBX::NodeAttribute (and subclasses) implementation
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef ASSIMP_BUILD_NO_FBX_IMPORTER
 | 
			
		||||
 | 
			
		||||
#include "FBXParser.h"
 | 
			
		||||
#include "FBXDocument.h"
 | 
			
		||||
#include "FBXImporter.h"
 | 
			
		||||
#include "FBXDocumentUtil.h"
 | 
			
		||||
 | 
			
		||||
namespace Assimp {
 | 
			
		||||
namespace FBX {
 | 
			
		||||
 | 
			
		||||
using namespace Util;
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
NodeAttribute::NodeAttribute(uint64_t id, const Element& element, const Document& doc, const std::string& name)
 | 
			
		||||
: Object(id,element,name)
 | 
			
		||||
, props()
 | 
			
		||||
{
 | 
			
		||||
    const Scope& sc = GetRequiredScope(element);
 | 
			
		||||
 | 
			
		||||
    const std::string& classname = ParseTokenAsString(GetRequiredToken(element,2));
 | 
			
		||||
 | 
			
		||||
    // hack on the deriving type but Null/LimbNode attributes are the only case in which
 | 
			
		||||
    // the property table is by design absent and no warning should be generated
 | 
			
		||||
    // for it.
 | 
			
		||||
    const bool is_null_or_limb = !strcmp(classname.c_str(), "Null") || !strcmp(classname.c_str(), "LimbNode");
 | 
			
		||||
    props = GetPropertyTable(doc,"NodeAttribute.Fbx" + classname,element,sc, is_null_or_limb);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
NodeAttribute::~NodeAttribute()
 | 
			
		||||
{
 | 
			
		||||
    // empty
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
CameraSwitcher::CameraSwitcher(uint64_t id, const Element& element, const Document& doc, const std::string& name)
 | 
			
		||||
    : NodeAttribute(id,element,doc,name)
 | 
			
		||||
{
 | 
			
		||||
    const Scope& sc = GetRequiredScope(element);
 | 
			
		||||
    const Element* const CameraId = sc["CameraId"];
 | 
			
		||||
    const Element* const CameraName = sc["CameraName"];
 | 
			
		||||
    const Element* const CameraIndexName = sc["CameraIndexName"];
 | 
			
		||||
 | 
			
		||||
    if(CameraId) {
 | 
			
		||||
        cameraId = ParseTokenAsInt(GetRequiredToken(*CameraId,0));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(CameraName) {
 | 
			
		||||
        cameraName = GetRequiredToken(*CameraName,0).StringContents();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(CameraIndexName && CameraIndexName->Tokens().size()) {
 | 
			
		||||
        cameraIndexName = GetRequiredToken(*CameraIndexName,0).StringContents();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
CameraSwitcher::~CameraSwitcher()
 | 
			
		||||
{
 | 
			
		||||
    // empty
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
Camera::Camera(uint64_t id, const Element& element, const Document& doc, const std::string& name)
 | 
			
		||||
: NodeAttribute(id,element,doc,name)
 | 
			
		||||
{
 | 
			
		||||
    // empty
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
Camera::~Camera()
 | 
			
		||||
{
 | 
			
		||||
    // empty
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
Light::Light(uint64_t id, const Element& element, const Document& doc, const std::string& name)
 | 
			
		||||
: NodeAttribute(id,element,doc,name)
 | 
			
		||||
{
 | 
			
		||||
    // empty
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
Light::~Light()
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
Null::Null(uint64_t id, const Element& element, const Document& doc, const std::string& name)
 | 
			
		||||
: NodeAttribute(id,element,doc,name)
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
Null::~Null()
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
LimbNode::LimbNode(uint64_t id, const Element& element, const Document& doc, const std::string& name)
 | 
			
		||||
: NodeAttribute(id,element,doc,name)
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
LimbNode::~LimbNode()
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										1309
									
								
								thirdparty/assimp/code/FBX/FBXParser.cpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1309
									
								
								thirdparty/assimp/code/FBX/FBXParser.cpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										235
									
								
								thirdparty/assimp/code/FBX/FBXParser.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										235
									
								
								thirdparty/assimp/code/FBX/FBXParser.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,235 @@
 | 
			
		||||
/*
 | 
			
		||||
Open Asset Import Library (assimp)
 | 
			
		||||
----------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
Copyright (c) 2006-2019, 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  FBXParser.h
 | 
			
		||||
 *  @brief FBX parsing code
 | 
			
		||||
 */
 | 
			
		||||
#ifndef INCLUDED_AI_FBX_PARSER_H
 | 
			
		||||
#define INCLUDED_AI_FBX_PARSER_H
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <map>
 | 
			
		||||
#include <memory>
 | 
			
		||||
#include <assimp/LogAux.h>
 | 
			
		||||
#include <assimp/fast_atof.h>
 | 
			
		||||
 | 
			
		||||
#include "FBXCompileConfig.h"
 | 
			
		||||
#include "FBXTokenizer.h"
 | 
			
		||||
 | 
			
		||||
namespace Assimp {
 | 
			
		||||
namespace FBX {
 | 
			
		||||
 | 
			
		||||
class Scope;
 | 
			
		||||
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
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/** FBX data entity that consists of a key:value tuple.
 | 
			
		||||
 *
 | 
			
		||||
 *  Example:
 | 
			
		||||
 *  @verbatim
 | 
			
		||||
 *    AnimationCurve: 23, "AnimCurve::", "" {
 | 
			
		||||
 *        [..]
 | 
			
		||||
 *    }
 | 
			
		||||
 *  @endverbatim
 | 
			
		||||
 *
 | 
			
		||||
 *  As can be seen in this sample, elements can contain nested #Scope
 | 
			
		||||
 *  as their trailing member.  **/
 | 
			
		||||
class Element
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    Element(const Token& key_token, Parser& parser);
 | 
			
		||||
    ~Element();
 | 
			
		||||
 | 
			
		||||
    const Scope* Compound() const {
 | 
			
		||||
        return compound.get();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const Token& KeyToken() const {
 | 
			
		||||
        return key_token;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const TokenList& Tokens() const {
 | 
			
		||||
        return tokens;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    const Token& key_token;
 | 
			
		||||
    TokenList tokens;
 | 
			
		||||
    std::unique_ptr<Scope> compound;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/** FBX data entity that consists of a 'scope', a collection
 | 
			
		||||
 *  of not necessarily unique #Element instances.
 | 
			
		||||
 *
 | 
			
		||||
 *  Example:
 | 
			
		||||
 *  @verbatim
 | 
			
		||||
 *    GlobalSettings:  {
 | 
			
		||||
 *        Version: 1000
 | 
			
		||||
 *        Properties70:
 | 
			
		||||
 *        [...]
 | 
			
		||||
 *    }
 | 
			
		||||
 *  @endverbatim  */
 | 
			
		||||
class Scope
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    Scope(Parser& parser, bool topLevel = false);
 | 
			
		||||
    ~Scope();
 | 
			
		||||
 | 
			
		||||
    const Element* operator[] (const std::string& index) const {
 | 
			
		||||
        ElementMap::const_iterator it = elements.find(index);
 | 
			
		||||
        return it == elements.end() ? NULL : (*it).second;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
	const Element* FindElementCaseInsensitive(const std::string& elementName) const {
 | 
			
		||||
		const char* elementNameCStr = elementName.c_str();
 | 
			
		||||
		for (auto element = elements.begin(); element != elements.end(); ++element)
 | 
			
		||||
		{
 | 
			
		||||
			if (!ASSIMP_strincmp(element->first.c_str(), elementNameCStr, MAXLEN)) {
 | 
			
		||||
				return element->second;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    ElementCollection GetCollection(const std::string& index) const {
 | 
			
		||||
        return elements.equal_range(index);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const ElementMap& Elements() const  {
 | 
			
		||||
        return elements;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    ElementMap elements;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/** FBX parsing class, takes a list of input tokens and generates a hierarchy
 | 
			
		||||
 *  of nested #Scope instances, representing the fbx DOM.*/
 | 
			
		||||
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();
 | 
			
		||||
 | 
			
		||||
    const Scope& GetRootScope() const {
 | 
			
		||||
        return *root.get();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool IsBinary() const {
 | 
			
		||||
        return is_binary;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    friend class Scope;
 | 
			
		||||
    friend class Element;
 | 
			
		||||
 | 
			
		||||
    TokenPtr AdvanceToNextToken();
 | 
			
		||||
    TokenPtr LastToken() const;
 | 
			
		||||
    TokenPtr CurrentToken() const;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    const TokenList& tokens;
 | 
			
		||||
 | 
			
		||||
    TokenPtr last, current;
 | 
			
		||||
    TokenList::const_iterator cursor;
 | 
			
		||||
    std::unique_ptr<Scope> root;
 | 
			
		||||
 | 
			
		||||
    const bool is_binary;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* token parsing - this happens when building the DOM out of the parse-tree*/
 | 
			
		||||
uint64_t ParseTokenAsID(const Token& t, const char*& err_out);
 | 
			
		||||
size_t ParseTokenAsDim(const Token& t, const char*& err_out);
 | 
			
		||||
 | 
			
		||||
float ParseTokenAsFloat(const Token& t, const char*& err_out);
 | 
			
		||||
int ParseTokenAsInt(const Token& t, const char*& err_out);
 | 
			
		||||
int64_t ParseTokenAsInt64(const Token& t, const char*& err_out);
 | 
			
		||||
std::string ParseTokenAsString(const Token& t, const char*& err_out);
 | 
			
		||||
 | 
			
		||||
/* wrapper around ParseTokenAsXXX() with DOMError handling */
 | 
			
		||||
uint64_t ParseTokenAsID(const Token& t);
 | 
			
		||||
size_t ParseTokenAsDim(const Token& t);
 | 
			
		||||
float ParseTokenAsFloat(const Token& t);
 | 
			
		||||
int ParseTokenAsInt(const Token& t);
 | 
			
		||||
int64_t ParseTokenAsInt64(const Token& t);
 | 
			
		||||
std::string ParseTokenAsString(const Token& t);
 | 
			
		||||
 | 
			
		||||
/* read data arrays */
 | 
			
		||||
void ParseVectorDataArray(std::vector<aiVector3D>& out, const Element& el);
 | 
			
		||||
void ParseVectorDataArray(std::vector<aiColor4D>& out, const Element& el);
 | 
			
		||||
void ParseVectorDataArray(std::vector<aiVector2D>& out, const Element& el);
 | 
			
		||||
void ParseVectorDataArray(std::vector<int>& out, const Element& el);
 | 
			
		||||
void ParseVectorDataArray(std::vector<float>& out, const Element& el);
 | 
			
		||||
void ParseVectorDataArray(std::vector<unsigned int>& out, const Element& el);
 | 
			
		||||
void ParseVectorDataArray(std::vector<uint64_t>& out, const Element& e);
 | 
			
		||||
void ParseVectorDataArray(std::vector<int64_t>& out, const Element& el);
 | 
			
		||||
 | 
			
		||||
bool HasElement( const Scope& sc, const std::string& index );
 | 
			
		||||
 | 
			
		||||
// extract a required element from a scope, abort if the element cannot be found
 | 
			
		||||
const Element& GetRequiredElement(const Scope& sc, const std::string& index, const Element* element = NULL);
 | 
			
		||||
 | 
			
		||||
// extract required compound scope
 | 
			
		||||
const Scope& GetRequiredScope(const Element& el);
 | 
			
		||||
// get token at a particular index
 | 
			
		||||
const Token& GetRequiredToken(const Element& el, unsigned int index);
 | 
			
		||||
 | 
			
		||||
// read a 4x4 matrix from an array of 16 floats
 | 
			
		||||
aiMatrix4x4 ReadMatrix(const Element& element);
 | 
			
		||||
 | 
			
		||||
} // ! FBX
 | 
			
		||||
} // ! Assimp
 | 
			
		||||
 | 
			
		||||
#endif // ! INCLUDED_AI_FBX_PARSER_H
 | 
			
		||||
							
								
								
									
										235
									
								
								thirdparty/assimp/code/FBX/FBXProperties.cpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										235
									
								
								thirdparty/assimp/code/FBX/FBXProperties.cpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,235 @@
 | 
			
		||||
/*
 | 
			
		||||
Open Asset Import Library (assimp)
 | 
			
		||||
----------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
Copyright (c) 2006-2019, 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  FBXProperties.cpp
 | 
			
		||||
 *  @brief Implementation of the FBX dynamic properties system
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef ASSIMP_BUILD_NO_FBX_IMPORTER
 | 
			
		||||
 | 
			
		||||
#include "FBXTokenizer.h"
 | 
			
		||||
#include "FBXParser.h"
 | 
			
		||||
#include "FBXDocument.h"
 | 
			
		||||
#include "FBXDocumentUtil.h"
 | 
			
		||||
#include "FBXProperties.h"
 | 
			
		||||
 | 
			
		||||
namespace Assimp {
 | 
			
		||||
namespace FBX {
 | 
			
		||||
 | 
			
		||||
    using namespace Util;
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
Property::Property()
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
Property::~Property()
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
namespace {
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
// read a typed property out of a FBX element. The return value is NULL if the property cannot be read.
 | 
			
		||||
Property* ReadTypedProperty(const Element& element)
 | 
			
		||||
{
 | 
			
		||||
    ai_assert(element.KeyToken().StringContents() == "P");
 | 
			
		||||
 | 
			
		||||
    const TokenList& tok = element.Tokens();
 | 
			
		||||
    ai_assert(tok.size() >= 5);
 | 
			
		||||
 | 
			
		||||
    const std::string& s = ParseTokenAsString(*tok[1]);
 | 
			
		||||
    const char* const cs = s.c_str();
 | 
			
		||||
    if (!strcmp(cs,"KString")) {
 | 
			
		||||
        return new TypedProperty<std::string>(ParseTokenAsString(*tok[4]));
 | 
			
		||||
    }
 | 
			
		||||
    else if (!strcmp(cs,"bool") || !strcmp(cs,"Bool")) {
 | 
			
		||||
        return new TypedProperty<bool>(ParseTokenAsInt(*tok[4]) != 0);
 | 
			
		||||
    }
 | 
			
		||||
    else if (!strcmp(cs, "int") || !strcmp(cs, "Int") || !strcmp(cs, "enum") || !strcmp(cs, "Enum")) {
 | 
			
		||||
        return new TypedProperty<int>(ParseTokenAsInt(*tok[4]));
 | 
			
		||||
    }
 | 
			
		||||
    else if (!strcmp(cs, "ULongLong")) {
 | 
			
		||||
        return new TypedProperty<uint64_t>(ParseTokenAsID(*tok[4]));
 | 
			
		||||
    }
 | 
			
		||||
    else if (!strcmp(cs, "KTime")) {
 | 
			
		||||
        return new TypedProperty<int64_t>(ParseTokenAsInt64(*tok[4]));
 | 
			
		||||
    }
 | 
			
		||||
    else if (!strcmp(cs,"Vector3D") ||
 | 
			
		||||
        !strcmp(cs,"ColorRGB") ||
 | 
			
		||||
        !strcmp(cs,"Vector") ||
 | 
			
		||||
        !strcmp(cs,"Color") ||
 | 
			
		||||
        !strcmp(cs,"Lcl Translation") ||
 | 
			
		||||
        !strcmp(cs,"Lcl Rotation") ||
 | 
			
		||||
        !strcmp(cs,"Lcl Scaling")
 | 
			
		||||
        ) {
 | 
			
		||||
        return new TypedProperty<aiVector3D>(aiVector3D(
 | 
			
		||||
            ParseTokenAsFloat(*tok[4]),
 | 
			
		||||
            ParseTokenAsFloat(*tok[5]),
 | 
			
		||||
            ParseTokenAsFloat(*tok[6]))
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
    else if (!strcmp(cs,"double") || !strcmp(cs,"Number") || !strcmp(cs,"Float") || !strcmp(cs,"FieldOfView") || !strcmp( cs, "UnitScaleFactor" ) ) {
 | 
			
		||||
        return new TypedProperty<float>(ParseTokenAsFloat(*tok[4]));
 | 
			
		||||
    }
 | 
			
		||||
    return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
// peek into an element and check if it contains a FBX property, if so return its name.
 | 
			
		||||
std::string PeekPropertyName(const Element& element)
 | 
			
		||||
{
 | 
			
		||||
    ai_assert(element.KeyToken().StringContents() == "P");
 | 
			
		||||
    const TokenList& tok = element.Tokens();
 | 
			
		||||
    if(tok.size() < 4) {
 | 
			
		||||
        return "";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return ParseTokenAsString(*tok[0]);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} //! anon
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
PropertyTable::PropertyTable()
 | 
			
		||||
: templateProps()
 | 
			
		||||
, element()
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
PropertyTable::PropertyTable(const Element& element, std::shared_ptr<const PropertyTable> templateProps)
 | 
			
		||||
: templateProps(templateProps)
 | 
			
		||||
, element(&element)
 | 
			
		||||
{
 | 
			
		||||
    const Scope& scope = GetRequiredScope(element);
 | 
			
		||||
    for(const ElementMap::value_type& v : scope.Elements()) {
 | 
			
		||||
        if(v.first != "P") {
 | 
			
		||||
            DOMWarning("expected only P elements in property table",v.second);
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const std::string& name = PeekPropertyName(*v.second);
 | 
			
		||||
        if(!name.length()) {
 | 
			
		||||
            DOMWarning("could not read property name",v.second);
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        LazyPropertyMap::const_iterator it = lazyProps.find(name);
 | 
			
		||||
        if (it != lazyProps.end()) {
 | 
			
		||||
            DOMWarning("duplicate property name, will hide previous value: " + name,v.second);
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        lazyProps[name] = v.second;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
PropertyTable::~PropertyTable()
 | 
			
		||||
{
 | 
			
		||||
    for(PropertyMap::value_type& v : props) {
 | 
			
		||||
        delete v.second;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
const Property* PropertyTable::Get(const std::string& name) const
 | 
			
		||||
{
 | 
			
		||||
    PropertyMap::const_iterator it = props.find(name);
 | 
			
		||||
    if (it == props.end()) {
 | 
			
		||||
        // hasn't been parsed yet?
 | 
			
		||||
        LazyPropertyMap::const_iterator lit = lazyProps.find(name);
 | 
			
		||||
        if(lit != lazyProps.end()) {
 | 
			
		||||
            props[name] = ReadTypedProperty(*(*lit).second);
 | 
			
		||||
            it = props.find(name);
 | 
			
		||||
 | 
			
		||||
            ai_assert(it != props.end());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (it == props.end()) {
 | 
			
		||||
            // check property template
 | 
			
		||||
            if(templateProps) {
 | 
			
		||||
                return templateProps->Get(name);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return NULL;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return (*it).second;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DirectPropertyMap PropertyTable::GetUnparsedProperties() const
 | 
			
		||||
{
 | 
			
		||||
    DirectPropertyMap result;
 | 
			
		||||
 | 
			
		||||
    // Loop through all the lazy properties (which is all the properties)
 | 
			
		||||
    for(const LazyPropertyMap::value_type& element : lazyProps) {
 | 
			
		||||
 | 
			
		||||
        // Skip parsed properties
 | 
			
		||||
        if (props.end() != props.find(element.first)) continue;
 | 
			
		||||
 | 
			
		||||
        // Read the element's value.
 | 
			
		||||
        // Wrap the naked pointer (since the call site is required to acquire ownership)
 | 
			
		||||
        // std::unique_ptr from C++11 would be preferred both as a wrapper and a return value.
 | 
			
		||||
        std::shared_ptr<Property> prop = std::shared_ptr<Property>(ReadTypedProperty(*element.second));
 | 
			
		||||
 | 
			
		||||
        // Element could not be read. Skip it.
 | 
			
		||||
        if (!prop) continue;
 | 
			
		||||
 | 
			
		||||
        // Add to result
 | 
			
		||||
        result[element.first] = prop;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} //! FBX
 | 
			
		||||
} //! Assimp
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										185
									
								
								thirdparty/assimp/code/FBX/FBXProperties.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										185
									
								
								thirdparty/assimp/code/FBX/FBXProperties.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,185 @@
 | 
			
		||||
/*
 | 
			
		||||
Open Asset Import Library (assimp)
 | 
			
		||||
----------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
Copyright (c) 2006-2019, 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  FBXProperties.h
 | 
			
		||||
 *  @brief FBX dynamic properties
 | 
			
		||||
 */
 | 
			
		||||
#ifndef INCLUDED_AI_FBX_PROPERTIES_H
 | 
			
		||||
#define INCLUDED_AI_FBX_PROPERTIES_H
 | 
			
		||||
 | 
			
		||||
#include "FBXCompileConfig.h"
 | 
			
		||||
#include <memory>
 | 
			
		||||
#include <string>
 | 
			
		||||
 | 
			
		||||
namespace Assimp {
 | 
			
		||||
namespace FBX {
 | 
			
		||||
 | 
			
		||||
// Forward declarations
 | 
			
		||||
class Element;
 | 
			
		||||
 | 
			
		||||
/** Represents a dynamic property. Type info added by deriving classes,
 | 
			
		||||
 *  see #TypedProperty.
 | 
			
		||||
 Example:
 | 
			
		||||
 @verbatim
 | 
			
		||||
   P: "ShininessExponent", "double", "Number", "",0.5
 | 
			
		||||
 @endvebatim
 | 
			
		||||
*/
 | 
			
		||||
class Property {
 | 
			
		||||
protected:
 | 
			
		||||
    Property();
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
    virtual ~Property();
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
    template <typename T>
 | 
			
		||||
    const T* As() const {
 | 
			
		||||
        return dynamic_cast<const T*>(this);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template<typename T>
 | 
			
		||||
class TypedProperty : public Property {
 | 
			
		||||
public:
 | 
			
		||||
    explicit TypedProperty(const T& value)
 | 
			
		||||
    : value(value) {
 | 
			
		||||
        // empty
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const T& Value() const {
 | 
			
		||||
        return value;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    T value;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
typedef std::fbx_unordered_map<std::string,std::shared_ptr<Property> > DirectPropertyMap;
 | 
			
		||||
typedef std::fbx_unordered_map<std::string,const Property*>            PropertyMap;
 | 
			
		||||
typedef std::fbx_unordered_map<std::string,const Element*>             LazyPropertyMap;
 | 
			
		||||
 | 
			
		||||
/** 
 | 
			
		||||
 *  Represents a property table as can be found in the newer FBX files (Properties60, Properties70)
 | 
			
		||||
 */
 | 
			
		||||
class PropertyTable {
 | 
			
		||||
public:
 | 
			
		||||
    // in-memory property table with no source element
 | 
			
		||||
    PropertyTable();
 | 
			
		||||
    PropertyTable(const Element& element, std::shared_ptr<const PropertyTable> templateProps);
 | 
			
		||||
    ~PropertyTable();
 | 
			
		||||
 | 
			
		||||
    const Property* Get(const std::string& name) const;
 | 
			
		||||
 | 
			
		||||
    // PropertyTable's need not be coupled with FBX elements so this can be NULL
 | 
			
		||||
    const Element* GetElement() const {
 | 
			
		||||
        return element;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const PropertyTable* TemplateProps() const {
 | 
			
		||||
        return templateProps.get();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    DirectPropertyMap GetUnparsedProperties() const;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    LazyPropertyMap lazyProps;
 | 
			
		||||
    mutable PropertyMap props;
 | 
			
		||||
    const std::shared_ptr<const PropertyTable> templateProps;
 | 
			
		||||
    const Element* const element;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
template <typename T>
 | 
			
		||||
inline 
 | 
			
		||||
T PropertyGet(const PropertyTable& in, const std::string& name, const T& defaultValue) {
 | 
			
		||||
    const Property* const prop = in.Get(name);
 | 
			
		||||
    if( nullptr == prop) {
 | 
			
		||||
        return defaultValue;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // strong typing, no need to be lenient
 | 
			
		||||
    const TypedProperty<T>* const tprop = prop->As< TypedProperty<T> >();
 | 
			
		||||
    if( nullptr == tprop) {
 | 
			
		||||
        return defaultValue;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return tprop->Value();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
template <typename T>
 | 
			
		||||
inline 
 | 
			
		||||
T PropertyGet(const PropertyTable& in, const std::string& name, bool& result, bool useTemplate=false ) {
 | 
			
		||||
    const Property* prop = in.Get(name);
 | 
			
		||||
    if( nullptr == prop) {
 | 
			
		||||
        if ( ! useTemplate ) {
 | 
			
		||||
            result = false;
 | 
			
		||||
            return T();
 | 
			
		||||
        }
 | 
			
		||||
        const PropertyTable* templ = in.TemplateProps();
 | 
			
		||||
        if ( nullptr == templ ) {
 | 
			
		||||
            result = false;
 | 
			
		||||
            return T();
 | 
			
		||||
        }
 | 
			
		||||
        prop = templ->Get(name);
 | 
			
		||||
        if ( nullptr == prop ) {
 | 
			
		||||
            result = false;
 | 
			
		||||
            return T();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // strong typing, no need to be lenient
 | 
			
		||||
    const TypedProperty<T>* const tprop = prop->As< TypedProperty<T> >();
 | 
			
		||||
    if( nullptr == tprop) {
 | 
			
		||||
        result = false;
 | 
			
		||||
        return T();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    result = true;
 | 
			
		||||
    return tprop->Value();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} //! FBX
 | 
			
		||||
} //! Assimp
 | 
			
		||||
 | 
			
		||||
#endif // INCLUDED_AI_FBX_PROPERTIES_H
 | 
			
		||||
							
								
								
									
										248
									
								
								thirdparty/assimp/code/FBX/FBXTokenizer.cpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										248
									
								
								thirdparty/assimp/code/FBX/FBXTokenizer.cpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,248 @@
 | 
			
		||||
/*
 | 
			
		||||
Open Asset Import Library (assimp)
 | 
			
		||||
----------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
Copyright (c) 2006-2019, 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  FBXTokenizer.cpp
 | 
			
		||||
 *  @brief Implementation of the FBX broadphase lexer
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef ASSIMP_BUILD_NO_FBX_IMPORTER
 | 
			
		||||
 | 
			
		||||
// tab width for logging columns
 | 
			
		||||
#define ASSIMP_FBX_TAB_WIDTH 4
 | 
			
		||||
 | 
			
		||||
#include <assimp/ParsingUtils.h>
 | 
			
		||||
 | 
			
		||||
#include "FBXTokenizer.h"
 | 
			
		||||
#include "FBXUtil.h"
 | 
			
		||||
#include <assimp/Exceptional.h>
 | 
			
		||||
 | 
			
		||||
namespace Assimp {
 | 
			
		||||
namespace FBX {
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
Token::Token(const char* sbegin, const char* send, TokenType type, unsigned int line, unsigned int column)
 | 
			
		||||
    :
 | 
			
		||||
#ifdef DEBUG
 | 
			
		||||
    contents(sbegin, static_cast<size_t>(send-sbegin)),
 | 
			
		||||
#endif
 | 
			
		||||
    sbegin(sbegin)
 | 
			
		||||
    , send(send)
 | 
			
		||||
    , type(type)
 | 
			
		||||
    , line(line)
 | 
			
		||||
    , column(column)
 | 
			
		||||
{
 | 
			
		||||
    ai_assert(sbegin);
 | 
			
		||||
    ai_assert(send);
 | 
			
		||||
 | 
			
		||||
    // tokens must be of non-zero length
 | 
			
		||||
    ai_assert(static_cast<size_t>(send-sbegin) > 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
Token::~Token()
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
namespace {
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
// signal tokenization error, this is always unrecoverable. Throws DeadlyImportError.
 | 
			
		||||
AI_WONT_RETURN void TokenizeError(const std::string& message, unsigned int line, unsigned int column) AI_WONT_RETURN_SUFFIX;
 | 
			
		||||
AI_WONT_RETURN void TokenizeError(const std::string& message, unsigned int line, unsigned int column)
 | 
			
		||||
{
 | 
			
		||||
    throw DeadlyImportError(Util::AddLineAndColumn("FBX-Tokenize",message,line,column));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// process a potential data token up to 'cur', adding it to 'output_tokens'.
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
void ProcessDataToken( TokenList& output_tokens, const char*& start, const char*& end,
 | 
			
		||||
                      unsigned int line,
 | 
			
		||||
                      unsigned int column,
 | 
			
		||||
                      TokenType type = TokenType_DATA,
 | 
			
		||||
                      bool must_have_token = false)
 | 
			
		||||
{
 | 
			
		||||
    if (start && end) {
 | 
			
		||||
        // sanity check:
 | 
			
		||||
        // tokens should have no whitespace outside quoted text and [start,end] should
 | 
			
		||||
        // properly delimit the valid range.
 | 
			
		||||
        bool in_double_quotes = false;
 | 
			
		||||
        for (const char* c = start; c != end + 1; ++c) {
 | 
			
		||||
            if (*c == '\"') {
 | 
			
		||||
                in_double_quotes = !in_double_quotes;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (!in_double_quotes && IsSpaceOrNewLine(*c)) {
 | 
			
		||||
                TokenizeError("unexpected whitespace in token", line, column);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (in_double_quotes) {
 | 
			
		||||
            TokenizeError("non-terminated double quotes", line, column);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        output_tokens.push_back(new_Token(start,end + 1,type,line,column));
 | 
			
		||||
    }
 | 
			
		||||
    else if (must_have_token) {
 | 
			
		||||
        TokenizeError("unexpected character, expected data token", line, column);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    start = end = NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
void Tokenize(TokenList& output_tokens, const char* input)
 | 
			
		||||
{
 | 
			
		||||
    ai_assert(input);
 | 
			
		||||
 | 
			
		||||
    // line and column numbers numbers are one-based
 | 
			
		||||
    unsigned int line = 1;
 | 
			
		||||
    unsigned int column = 1;
 | 
			
		||||
 | 
			
		||||
    bool comment = false;
 | 
			
		||||
    bool in_double_quotes = false;
 | 
			
		||||
    bool pending_data_token = false;
 | 
			
		||||
 | 
			
		||||
    const char* token_begin = NULL, *token_end = NULL;
 | 
			
		||||
    for (const char* cur = input;*cur;column += (*cur == '\t' ? ASSIMP_FBX_TAB_WIDTH : 1), ++cur) {
 | 
			
		||||
        const char c = *cur;
 | 
			
		||||
 | 
			
		||||
        if (IsLineEnd(c)) {
 | 
			
		||||
            comment = false;
 | 
			
		||||
 | 
			
		||||
            column = 0;
 | 
			
		||||
            ++line;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if(comment) {
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if(in_double_quotes) {
 | 
			
		||||
            if (c == '\"') {
 | 
			
		||||
                in_double_quotes = false;
 | 
			
		||||
                token_end = cur;
 | 
			
		||||
 | 
			
		||||
                ProcessDataToken(output_tokens,token_begin,token_end,line,column);
 | 
			
		||||
                pending_data_token = false;
 | 
			
		||||
            }
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        switch(c)
 | 
			
		||||
        {
 | 
			
		||||
        case '\"':
 | 
			
		||||
            if (token_begin) {
 | 
			
		||||
                TokenizeError("unexpected double-quote", line, column);
 | 
			
		||||
            }
 | 
			
		||||
            token_begin = cur;
 | 
			
		||||
            in_double_quotes = true;
 | 
			
		||||
            continue;
 | 
			
		||||
 | 
			
		||||
        case ';':
 | 
			
		||||
            ProcessDataToken(output_tokens,token_begin,token_end,line,column);
 | 
			
		||||
            comment = true;
 | 
			
		||||
            continue;
 | 
			
		||||
 | 
			
		||||
        case '{':
 | 
			
		||||
            ProcessDataToken(output_tokens,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);
 | 
			
		||||
            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);
 | 
			
		||||
            }
 | 
			
		||||
            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);
 | 
			
		||||
            }
 | 
			
		||||
            else {
 | 
			
		||||
                TokenizeError("unexpected colon", line, column);
 | 
			
		||||
            }
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (IsSpaceOrNewLine(c)) {
 | 
			
		||||
 | 
			
		||||
            if (token_begin) {
 | 
			
		||||
                // peek ahead and check if the next token is a colon in which
 | 
			
		||||
                // case this counts as KEY token.
 | 
			
		||||
                TokenType type = TokenType_DATA;
 | 
			
		||||
                for (const char* peek = cur;  *peek && IsSpaceOrNewLine(*peek); ++peek) {
 | 
			
		||||
                    if (*peek == ':') {
 | 
			
		||||
                        type = TokenType_KEY;
 | 
			
		||||
                        cur = peek;
 | 
			
		||||
                        break;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                ProcessDataToken(output_tokens,token_begin,token_end,line,column,type);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            pending_data_token = false;
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
            token_end = cur;
 | 
			
		||||
            if (!token_begin) {
 | 
			
		||||
                token_begin = cur;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            pending_data_token = true;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // !FBX
 | 
			
		||||
} // !Assimp
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										187
									
								
								thirdparty/assimp/code/FBX/FBXTokenizer.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										187
									
								
								thirdparty/assimp/code/FBX/FBXTokenizer.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,187 @@
 | 
			
		||||
/*
 | 
			
		||||
Open Asset Import Library (assimp)
 | 
			
		||||
----------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
Copyright (c) 2006-2019, 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  FBXTokenizer.h
 | 
			
		||||
 *  @brief FBX lexer
 | 
			
		||||
 */
 | 
			
		||||
#ifndef INCLUDED_AI_FBX_TOKENIZER_H
 | 
			
		||||
#define INCLUDED_AI_FBX_TOKENIZER_H
 | 
			
		||||
 | 
			
		||||
#include "FBXCompileConfig.h"
 | 
			
		||||
#include <assimp/ai_assert.h>
 | 
			
		||||
#include <vector>
 | 
			
		||||
#include <string>
 | 
			
		||||
 | 
			
		||||
namespace Assimp {
 | 
			
		||||
namespace FBX {
 | 
			
		||||
 | 
			
		||||
/** Rough classification for text FBX tokens used for constructing the
 | 
			
		||||
 *  basic scope hierarchy. */
 | 
			
		||||
enum TokenType
 | 
			
		||||
{
 | 
			
		||||
    // {
 | 
			
		||||
    TokenType_OPEN_BRACKET = 0,
 | 
			
		||||
 | 
			
		||||
    // }
 | 
			
		||||
    TokenType_CLOSE_BRACKET,
 | 
			
		||||
 | 
			
		||||
    // '"blablubb"', '2', '*14' - very general token class,
 | 
			
		||||
    // further processing happens at a later stage.
 | 
			
		||||
    TokenType_DATA,
 | 
			
		||||
 | 
			
		||||
    //
 | 
			
		||||
    TokenType_BINARY_DATA,
 | 
			
		||||
 | 
			
		||||
    // ,
 | 
			
		||||
    TokenType_COMMA,
 | 
			
		||||
 | 
			
		||||
    // blubb:
 | 
			
		||||
    TokenType_KEY
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/** Represents a single token in a FBX file. Tokens are
 | 
			
		||||
 *  classified by the #TokenType enumerated types.
 | 
			
		||||
 *
 | 
			
		||||
 *  Offers iterator protocol. Tokens are immutable. */
 | 
			
		||||
class Token
 | 
			
		||||
{
 | 
			
		||||
private:
 | 
			
		||||
    static const unsigned int BINARY_MARKER = static_cast<unsigned int>(-1);
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
    /** construct a textual token */
 | 
			
		||||
    Token(const char* sbegin, const char* send, TokenType type, unsigned int line, unsigned int column);
 | 
			
		||||
 | 
			
		||||
    /** construct a binary token */
 | 
			
		||||
    Token(const char* sbegin, const char* send, TokenType type, size_t offset);
 | 
			
		||||
 | 
			
		||||
    ~Token();
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
    std::string StringContents() const {
 | 
			
		||||
        return std::string(begin(),end());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool IsBinary() const {
 | 
			
		||||
        return column == BINARY_MARKER;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const char* begin() const {
 | 
			
		||||
        return sbegin;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const char* end() const {
 | 
			
		||||
        return send;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    TokenType Type() const {
 | 
			
		||||
        return type;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    size_t Offset() const {
 | 
			
		||||
        ai_assert(IsBinary());
 | 
			
		||||
        return offset;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    unsigned int Line() const {
 | 
			
		||||
        ai_assert(!IsBinary());
 | 
			
		||||
        return static_cast<unsigned int>(line);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    unsigned int Column() const {
 | 
			
		||||
        ai_assert(!IsBinary());
 | 
			
		||||
        return column;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
 | 
			
		||||
#ifdef DEBUG
 | 
			
		||||
    // full string copy for the sole purpose that it nicely appears
 | 
			
		||||
    // in msvc's debugger window.
 | 
			
		||||
    const std::string contents;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    const char* const sbegin;
 | 
			
		||||
    const char* const send;
 | 
			
		||||
    const TokenType type;
 | 
			
		||||
 | 
			
		||||
    union {
 | 
			
		||||
        size_t line;
 | 
			
		||||
        size_t offset;
 | 
			
		||||
    };
 | 
			
		||||
    const unsigned int column;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// XXX should use C++11's unique_ptr - but assimp's need to keep working with 03
 | 
			
		||||
typedef const Token* TokenPtr;
 | 
			
		||||
typedef std::vector< TokenPtr > TokenList;
 | 
			
		||||
 | 
			
		||||
#define new_Token new Token
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/** Main FBX tokenizer function. Transform input buffer into a list of preprocessed tokens.
 | 
			
		||||
 *
 | 
			
		||||
 *  Skips over comments and generates line and column numbers.
 | 
			
		||||
 *
 | 
			
		||||
 * @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);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/** Tokenizer function for binary FBX files.
 | 
			
		||||
 *
 | 
			
		||||
 *  Emits a token list suitable for direct parsing.
 | 
			
		||||
 *
 | 
			
		||||
 * @param output_tokens Receives a list of all tokens in the input data.
 | 
			
		||||
 * @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);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
} // ! FBX
 | 
			
		||||
} // ! Assimp
 | 
			
		||||
 | 
			
		||||
#endif // ! INCLUDED_AI_FBX_PARSER_H
 | 
			
		||||
							
								
								
									
										243
									
								
								thirdparty/assimp/code/FBX/FBXUtil.cpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										243
									
								
								thirdparty/assimp/code/FBX/FBXUtil.cpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,243 @@
 | 
			
		||||
/*
 | 
			
		||||
Open Asset Import Library (assimp)
 | 
			
		||||
----------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
Copyright (c) 2006-2019, 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  FBXUtil.cpp
 | 
			
		||||
 *  @brief Implementation of internal FBX utility functions
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "FBXUtil.h"
 | 
			
		||||
#include "FBXTokenizer.h"
 | 
			
		||||
 | 
			
		||||
#include <assimp/TinyFormatter.h>
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <cstring>
 | 
			
		||||
 | 
			
		||||
#ifndef ASSIMP_BUILD_NO_FBX_IMPORTER
 | 
			
		||||
 | 
			
		||||
namespace Assimp {
 | 
			
		||||
namespace FBX {
 | 
			
		||||
namespace Util {
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
const char* TokenTypeString(TokenType t)
 | 
			
		||||
{
 | 
			
		||||
    switch(t) {
 | 
			
		||||
        case TokenType_OPEN_BRACKET:
 | 
			
		||||
            return "TOK_OPEN_BRACKET";
 | 
			
		||||
 | 
			
		||||
        case TokenType_CLOSE_BRACKET:
 | 
			
		||||
            return "TOK_CLOSE_BRACKET";
 | 
			
		||||
 | 
			
		||||
        case TokenType_DATA:
 | 
			
		||||
            return "TOK_DATA";
 | 
			
		||||
 | 
			
		||||
        case TokenType_COMMA:
 | 
			
		||||
            return "TOK_COMMA";
 | 
			
		||||
 | 
			
		||||
        case TokenType_KEY:
 | 
			
		||||
            return "TOK_KEY";
 | 
			
		||||
 | 
			
		||||
        case TokenType_BINARY_DATA:
 | 
			
		||||
            return "TOK_BINARY_DATA";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ai_assert(false);
 | 
			
		||||
    return "";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
std::string AddOffset(const std::string& prefix, const std::string& text, size_t offset)
 | 
			
		||||
{
 | 
			
		||||
    return static_cast<std::string>( (Formatter::format() << prefix << " (offset 0x" << std::hex << offset << ") " << text) );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
std::string AddLineAndColumn(const std::string& prefix, const std::string& text, unsigned int line, unsigned int column)
 | 
			
		||||
{
 | 
			
		||||
    return static_cast<std::string>( (Formatter::format() << prefix << " (line " << line << " <<  col " << column << ") " << text) );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
std::string AddTokenText(const std::string& prefix, const std::string& text, const Token* tok)
 | 
			
		||||
{
 | 
			
		||||
    if(tok->IsBinary()) {
 | 
			
		||||
        return static_cast<std::string>( (Formatter::format() << prefix <<
 | 
			
		||||
            " (" << TokenTypeString(tok->Type()) <<
 | 
			
		||||
            ", offset 0x" << std::hex << tok->Offset() << ") " <<
 | 
			
		||||
            text) );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return static_cast<std::string>( (Formatter::format() << prefix <<
 | 
			
		||||
        " (" << TokenTypeString(tok->Type()) <<
 | 
			
		||||
        ", line " << tok->Line() <<
 | 
			
		||||
        ", col " << tok->Column() << ") " <<
 | 
			
		||||
        text) );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Generated by this formula: T["ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[i]] = i;
 | 
			
		||||
static const uint8_t base64DecodeTable[128] = {
 | 
			
		||||
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
 | 
			
		||||
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
 | 
			
		||||
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 62, 255, 255, 255, 63,
 | 
			
		||||
    52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255, 255, 255, 255, 255,
 | 
			
		||||
    255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
 | 
			
		||||
    15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 255, 255, 255, 255, 255,
 | 
			
		||||
    255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
 | 
			
		||||
    41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 255, 255, 255, 255, 255
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
uint8_t DecodeBase64(char ch)
 | 
			
		||||
{
 | 
			
		||||
    const auto idx = static_cast<uint8_t>(ch);
 | 
			
		||||
    if (idx > 127)
 | 
			
		||||
        return 255;
 | 
			
		||||
    return base64DecodeTable[idx];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
size_t ComputeDecodedSizeBase64(const char* in, size_t inLength)
 | 
			
		||||
{
 | 
			
		||||
    if (inLength < 2)
 | 
			
		||||
    {
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
    const size_t equals = size_t(in[inLength - 1] == '=') + size_t(in[inLength - 2] == '=');
 | 
			
		||||
    const size_t full_length = (inLength * 3) >> 2; // div by 4
 | 
			
		||||
    if (full_length < equals)
 | 
			
		||||
    {
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
    return full_length - equals;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
size_t DecodeBase64(const char* in, size_t inLength, uint8_t* out, size_t maxOutLength)
 | 
			
		||||
{
 | 
			
		||||
    if (maxOutLength == 0 || inLength < 2) {
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
    const size_t realLength = inLength - size_t(in[inLength - 1] == '=') - size_t(in[inLength - 2] == '=');
 | 
			
		||||
    size_t dst_offset = 0;
 | 
			
		||||
    int val = 0, valb = -8;
 | 
			
		||||
    for (size_t src_offset = 0; src_offset < realLength; ++src_offset)
 | 
			
		||||
    {
 | 
			
		||||
        const uint8_t table_value = Util::DecodeBase64(in[src_offset]);
 | 
			
		||||
        if (table_value == 255)
 | 
			
		||||
        {
 | 
			
		||||
            return 0;
 | 
			
		||||
        }
 | 
			
		||||
        val = (val << 6) + table_value;
 | 
			
		||||
        valb += 6;
 | 
			
		||||
        if (valb >= 0)
 | 
			
		||||
        {
 | 
			
		||||
            out[dst_offset++] = static_cast<uint8_t>((val >> valb) & 0xFF);
 | 
			
		||||
            valb -= 8;
 | 
			
		||||
            val &= 0xFFF;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return dst_offset;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const char to_base64_string[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
 | 
			
		||||
char EncodeBase64(char byte)
 | 
			
		||||
{
 | 
			
		||||
    return to_base64_string[(size_t)byte];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** Encodes a block of 4 bytes to base64 encoding
 | 
			
		||||
*
 | 
			
		||||
*  @param bytes Bytes to encode.
 | 
			
		||||
*  @param out_string String to write encoded values to.
 | 
			
		||||
*  @param string_pos Position in out_string.*/
 | 
			
		||||
void EncodeByteBlock(const char* bytes, std::string& out_string, size_t string_pos)
 | 
			
		||||
{
 | 
			
		||||
    char b0 = (bytes[0] & 0xFC) >> 2;
 | 
			
		||||
    char b1 = (bytes[0] & 0x03) << 4 | ((bytes[1] & 0xF0) >> 4);
 | 
			
		||||
    char b2 = (bytes[1] & 0x0F) << 2 | ((bytes[2] & 0xC0) >> 6);
 | 
			
		||||
    char b3 = (bytes[2] & 0x3F);
 | 
			
		||||
 | 
			
		||||
    out_string[string_pos + 0] = EncodeBase64(b0);
 | 
			
		||||
    out_string[string_pos + 1] = EncodeBase64(b1);
 | 
			
		||||
    out_string[string_pos + 2] = EncodeBase64(b2);
 | 
			
		||||
    out_string[string_pos + 3] = EncodeBase64(b3);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::string EncodeBase64(const char* data, size_t length)
 | 
			
		||||
{
 | 
			
		||||
    // calculate extra bytes needed to get a multiple of 3
 | 
			
		||||
    size_t extraBytes = 3 - length % 3;
 | 
			
		||||
 | 
			
		||||
    // number of base64 bytes
 | 
			
		||||
    size_t encodedBytes = 4 * (length + extraBytes) / 3;
 | 
			
		||||
 | 
			
		||||
    std::string encoded_string(encodedBytes, '=');
 | 
			
		||||
 | 
			
		||||
    // read blocks of 3 bytes
 | 
			
		||||
    for (size_t ib3 = 0; ib3 < length / 3; ib3++)
 | 
			
		||||
    {
 | 
			
		||||
        const size_t iByte = ib3 * 3;
 | 
			
		||||
        const size_t iEncodedByte = ib3 * 4;
 | 
			
		||||
        const char* currData = &data[iByte];
 | 
			
		||||
 | 
			
		||||
        EncodeByteBlock(currData, encoded_string, iEncodedByte);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // if size of data is not a multiple of 3, also encode the final bytes (and add zeros where needed)
 | 
			
		||||
    if (extraBytes > 0)
 | 
			
		||||
    {
 | 
			
		||||
        char finalBytes[4] = { 0,0,0,0 };
 | 
			
		||||
        memcpy(&finalBytes[0], &data[length - length % 3], length % 3);
 | 
			
		||||
 | 
			
		||||
        const size_t iEncodedByte = encodedBytes - 4;
 | 
			
		||||
        EncodeByteBlock(&finalBytes[0], encoded_string, iEncodedByte);
 | 
			
		||||
 | 
			
		||||
        // add '=' at the end
 | 
			
		||||
        for (size_t i = 0; i < 4 * extraBytes / 3; i++)
 | 
			
		||||
            encoded_string[encodedBytes - i - 1] = '=';
 | 
			
		||||
    }
 | 
			
		||||
    return encoded_string;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // !Util
 | 
			
		||||
} // !FBX
 | 
			
		||||
} // !Assimp
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										137
									
								
								thirdparty/assimp/code/FBX/FBXUtil.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										137
									
								
								thirdparty/assimp/code/FBX/FBXUtil.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,137 @@
 | 
			
		||||
/*
 | 
			
		||||
Open Asset Import Library (assimp)
 | 
			
		||||
----------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
Copyright (c) 2006-2019, 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  FBXUtil.h
 | 
			
		||||
 *  @brief FBX utility functions for internal use
 | 
			
		||||
 */
 | 
			
		||||
#ifndef INCLUDED_AI_FBX_UTIL_H
 | 
			
		||||
#define INCLUDED_AI_FBX_UTIL_H
 | 
			
		||||
 | 
			
		||||
#include "FBXCompileConfig.h"
 | 
			
		||||
#include "FBXTokenizer.h"
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
 | 
			
		||||
namespace Assimp {
 | 
			
		||||
namespace FBX {
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
namespace Util {
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/** helper for std::for_each to delete all heap-allocated items in a container */
 | 
			
		||||
template<typename T>
 | 
			
		||||
struct delete_fun
 | 
			
		||||
{
 | 
			
		||||
    void operator()(const volatile T* del) {
 | 
			
		||||
        delete del;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/** Get a string representation for a #TokenType. */
 | 
			
		||||
const char* TokenTypeString(TokenType t);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/** Format log/error messages using a given offset in the source binary file
 | 
			
		||||
 *
 | 
			
		||||
 *  @param prefix Message prefix to be preprended to the location info.
 | 
			
		||||
 *  @param text Message text
 | 
			
		||||
 *  @param line Line index, 1-based
 | 
			
		||||
 *  @param column Column index, 1-based
 | 
			
		||||
 *  @return A string of the following format: {prefix} (offset 0x{offset}) {text}*/
 | 
			
		||||
std::string AddOffset(const std::string& prefix, const std::string& text, size_t offset);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/** Format log/error messages using a given line location in the source file.
 | 
			
		||||
 *
 | 
			
		||||
 *  @param prefix Message prefix to be preprended to the location info.
 | 
			
		||||
 *  @param text Message text
 | 
			
		||||
 *  @param line Line index, 1-based
 | 
			
		||||
 *  @param column Column index, 1-based
 | 
			
		||||
 *  @return A string of the following format: {prefix} (line {line}, col {column}) {text}*/
 | 
			
		||||
std::string AddLineAndColumn(const std::string& prefix, const std::string& text, unsigned int line, unsigned int column);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/** Format log/error messages using a given cursor token.
 | 
			
		||||
 *
 | 
			
		||||
 *  @param prefix Message prefix to be preprended to the location info.
 | 
			
		||||
 *  @param text Message text
 | 
			
		||||
 *  @param tok Token where parsing/processing stopped
 | 
			
		||||
 *  @return A string of the following format: {prefix} ({token-type}, line {line}, col {column}) {text}*/
 | 
			
		||||
std::string AddTokenText(const std::string& prefix, const std::string& text, const Token* tok);
 | 
			
		||||
 | 
			
		||||
/** Decode a single Base64-encoded character.
 | 
			
		||||
*
 | 
			
		||||
*  @param ch Character to decode (from base64 to binary).
 | 
			
		||||
*  @return decoded byte value*/
 | 
			
		||||
uint8_t DecodeBase64(char ch);
 | 
			
		||||
 | 
			
		||||
/** Compute decoded size of a Base64-encoded string
 | 
			
		||||
*
 | 
			
		||||
*  @param in Characters to decode.
 | 
			
		||||
*  @param inLength Number of characters to decode.
 | 
			
		||||
*  @return size of the decoded data (number of bytes)*/
 | 
			
		||||
size_t ComputeDecodedSizeBase64(const char* in, size_t inLength);
 | 
			
		||||
 | 
			
		||||
/** Decode a Base64-encoded string
 | 
			
		||||
*
 | 
			
		||||
*  @param in Characters to decode.
 | 
			
		||||
*  @param inLength Number of characters to decode.
 | 
			
		||||
*  @param out Pointer where we will store the decoded data.
 | 
			
		||||
*  @param maxOutLength Size of output buffer.
 | 
			
		||||
*  @return size of the decoded data (number of bytes)*/
 | 
			
		||||
size_t DecodeBase64(const char* in, size_t inLength, uint8_t* out, size_t maxOutLength);
 | 
			
		||||
 | 
			
		||||
char EncodeBase64(char byte);
 | 
			
		||||
 | 
			
		||||
/** Encode bytes in base64-encoding
 | 
			
		||||
*
 | 
			
		||||
*  @param data Binary data to encode.
 | 
			
		||||
*  @param inLength Number of bytes to encode.
 | 
			
		||||
*  @return base64-encoded string*/
 | 
			
		||||
std::string EncodeBase64(const char* data, size_t length);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif // ! INCLUDED_AI_FBX_UTIL_H
 | 
			
		||||
		Reference in New Issue
	
	Block a user