nuclear@0: /*
nuclear@0: Open Asset Import Library (assimp)
nuclear@0: ----------------------------------------------------------------------
nuclear@0: 
nuclear@0: Copyright (c) 2006-2012, assimp team
nuclear@0: All rights reserved.
nuclear@0: 
nuclear@0: Redistribution and use of this software in source and binary forms, 
nuclear@0: with or without modification, are permitted provided that the 
nuclear@0: following conditions are met:
nuclear@0: 
nuclear@0: * Redistributions of source code must retain the above
nuclear@0:   copyright notice, this list of conditions and the
nuclear@0:   following disclaimer.
nuclear@0: 
nuclear@0: * Redistributions in binary form must reproduce the above
nuclear@0:   copyright notice, this list of conditions and the
nuclear@0:   following disclaimer in the documentation and/or other
nuclear@0:   materials provided with the distribution.
nuclear@0: 
nuclear@0: * Neither the name of the assimp team, nor the names of its
nuclear@0:   contributors may be used to endorse or promote products
nuclear@0:   derived from this software without specific prior
nuclear@0:   written permission of the assimp team.
nuclear@0: 
nuclear@0: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
nuclear@0: "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
nuclear@0: LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
nuclear@0: A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
nuclear@0: OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
nuclear@0: SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
nuclear@0: LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
nuclear@0: DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
nuclear@0: THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
nuclear@0: (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
nuclear@0: OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
nuclear@0: 
nuclear@0: ----------------------------------------------------------------------
nuclear@0: */
nuclear@0: 
nuclear@0: /** @file  FBXImporter.cpp
nuclear@0:  *  @brief Implementation of the FBX importer.
nuclear@0:  */
nuclear@0: #include "AssimpPCH.h"
nuclear@0: 
nuclear@0: #ifndef ASSIMP_BUILD_NO_FBX_IMPORTER
nuclear@0: 
nuclear@0: #include <exception>
nuclear@0: #include <iterator>
nuclear@0: #include <boost/tuple/tuple.hpp>
nuclear@0: 
nuclear@0: #include "FBXImporter.h"
nuclear@0: 
nuclear@0: #include "FBXTokenizer.h"
nuclear@0: #include "FBXParser.h"
nuclear@0: #include "FBXUtil.h"
nuclear@0: #include "FBXDocument.h"
nuclear@0: #include "FBXConverter.h"
nuclear@0: 
nuclear@0: #include "StreamReader.h"
nuclear@0: #include "MemoryIOWrapper.h"
nuclear@0: 
nuclear@0: namespace Assimp {
nuclear@0: 	template<> const std::string LogFunctions<FBXImporter>::log_prefix = "FBX: ";
nuclear@0: }
nuclear@0: 
nuclear@0: using namespace Assimp;
nuclear@0: using namespace Assimp::Formatter;
nuclear@0: using namespace Assimp::FBX;
nuclear@0: 
nuclear@0: namespace {
nuclear@0: static const aiImporterDesc desc = {
nuclear@0: 	"Autodesk FBX Importer",
nuclear@0: 	"",
nuclear@0: 	"",
nuclear@0: 	"",
nuclear@0: 	aiImporterFlags_SupportTextFlavour,
nuclear@0: 	0,
nuclear@0: 	0,
nuclear@0: 	0,
nuclear@0: 	0,
nuclear@0: 	"fbx" 
nuclear@0: };
nuclear@0: }
nuclear@0: 
nuclear@0: // ------------------------------------------------------------------------------------------------
nuclear@0: // Constructor to be privately used by #Importer
nuclear@0: FBXImporter::FBXImporter()
nuclear@0: {}
nuclear@0: 
nuclear@0: // ------------------------------------------------------------------------------------------------
nuclear@0: // Destructor, private as well 
nuclear@0: FBXImporter::~FBXImporter()
nuclear@0: {
nuclear@0: }
nuclear@0: 
nuclear@0: // ------------------------------------------------------------------------------------------------
nuclear@0: // Returns whether the class can handle the format of the given file. 
nuclear@0: bool FBXImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const
nuclear@0: {
nuclear@0: 	const std::string& extension = GetExtension(pFile);
nuclear@0: 	if (extension == "fbx") {
nuclear@0: 		return true;
nuclear@0: 	}
nuclear@0: 
nuclear@0: 	else if ((!extension.length() || checkSig) && pIOHandler)	{
nuclear@0: 		// at least ascii FBX files usually have a 'FBX' somewhere in their head
nuclear@0: 		const char* tokens[] = {"FBX"};
nuclear@0: 		return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1);
nuclear@0: 	}
nuclear@0: 	return false;
nuclear@0: }
nuclear@0: 
nuclear@0: // ------------------------------------------------------------------------------------------------
nuclear@0: // List all extensions handled by this loader
nuclear@0: const aiImporterDesc* FBXImporter::GetInfo () const
nuclear@0: {
nuclear@0: 	return &desc;
nuclear@0: }
nuclear@0: 
nuclear@0: 
nuclear@0: // ------------------------------------------------------------------------------------------------
nuclear@0: // Setup configuration properties for the loader
nuclear@0: void FBXImporter::SetupProperties(const Importer* pImp)
nuclear@0: {
nuclear@0: 	settings.readAllLayers = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_ALL_GEOMETRY_LAYERS, true);
nuclear@0: 	settings.readAllMaterials = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_ALL_MATERIALS, false);
nuclear@0: 	settings.readMaterials = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_MATERIALS, true);
nuclear@0: 	settings.readCameras = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_CAMERAS, true);
nuclear@0: 	settings.readLights = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_LIGHTS, true);
nuclear@0: 	settings.readAnimations = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_ANIMATIONS, true);
nuclear@0: 	settings.strictMode = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_STRICT_MODE, false);
nuclear@0: 	settings.preservePivots = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_PRESERVE_PIVOTS, true);
nuclear@0: 	settings.optimizeEmptyAnimationCurves = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_OPTIMIZE_EMPTY_ANIMATION_CURVES, true);
nuclear@0: }
nuclear@0: 
nuclear@0: 
nuclear@0: // ------------------------------------------------------------------------------------------------
nuclear@0: // Imports the given file into the given scene structure. 
nuclear@0: void FBXImporter::InternReadFile( const std::string& pFile, 
nuclear@0: 	aiScene* pScene, IOSystem* pIOHandler)
nuclear@0: {
nuclear@0: 	boost::scoped_ptr<IOStream> stream(pIOHandler->Open(pFile,"rb"));
nuclear@0: 	if (!stream) {
nuclear@0: 		ThrowException("Could not open file for reading");
nuclear@0: 	}
nuclear@0: 
nuclear@0: 	// read entire file into memory - no streaming for this, fbx
nuclear@0: 	// files can grow large, but the assimp output data structure
nuclear@0: 	// then becomes very large, too. Assimp doesn't support
nuclear@0: 	// streaming for its output data structures so the net win with
nuclear@0: 	// streaming input data would be very low.
nuclear@0: 	std::vector<char> contents;
nuclear@0: 	contents.resize(stream->FileSize());
nuclear@0: 
nuclear@0: 	stream->Read(&*contents.begin(),contents.size(),1);
nuclear@0: 	const char* const begin = &*contents.begin();
nuclear@0: 
nuclear@0: 	// broadphase tokenizing pass in which we identify the core
nuclear@0: 	// syntax elements of FBX (brackets, commas, key:value mappings)
nuclear@0: 	TokenList tokens;
nuclear@0: 	try {
nuclear@0: 
nuclear@0: 		bool is_binary = false;
nuclear@0: 		if (!strncmp(begin,"Kaydara FBX Binary",18)) {
nuclear@0: 			is_binary = true;
nuclear@0: 			TokenizeBinary(tokens,begin,contents.size());
nuclear@0: 		}
nuclear@0: 		else {
nuclear@0: 			Tokenize(tokens,begin);
nuclear@0: 		}
nuclear@0: 
nuclear@0: 		// use this information to construct a very rudimentary 
nuclear@0: 		// parse-tree representing the FBX scope structure
nuclear@0: 		Parser parser(tokens, is_binary);
nuclear@0: 
nuclear@0: 		// take the raw parse-tree and convert it to a FBX DOM
nuclear@0: 		Document doc(parser,settings);
nuclear@0: 
nuclear@0: 		// convert the FBX DOM to aiScene
nuclear@0: 		ConvertToAssimpScene(pScene,doc);
nuclear@0: 	}
nuclear@0: 	catch(std::exception&) {
nuclear@0: 		std::for_each(tokens.begin(),tokens.end(),Util::delete_fun<Token>());
nuclear@0: 		throw;
nuclear@0: 	}
nuclear@0: }
nuclear@0: 
nuclear@0: #endif // !ASSIMP_BUILD_NO_FBX_IMPORTER