summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/assimp/code/BVHLoader.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/assimp/code/BVHLoader.cpp')
-rw-r--r--src/3rdparty/assimp/code/BVHLoader.cpp779
1 files changed, 394 insertions, 385 deletions
diff --git a/src/3rdparty/assimp/code/BVHLoader.cpp b/src/3rdparty/assimp/code/BVHLoader.cpp
index 35a3e20ef..ca6c5d36c 100644
--- a/src/3rdparty/assimp/code/BVHLoader.cpp
+++ b/src/3rdparty/assimp/code/BVHLoader.cpp
@@ -4,12 +4,12 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+Copyright (c) 2006-2016, 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
+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
@@ -26,46 +26,55 @@ 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
+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
+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
+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
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
-#include "AssimpPCH.h"
+
#ifndef ASSIMP_BUILD_NO_BVH_IMPORTER
#include "BVHLoader.h"
#include "fast_atof.h"
#include "SkeletonMeshBuilder.h"
+#include <assimp/Importer.hpp>
+#include <memory>
+#include "TinyFormatter.h"
+#include <assimp/IOSystem.hpp>
+#include <assimp/scene.h>
using namespace Assimp;
+using namespace Assimp::Formatter;
static const aiImporterDesc desc = {
- "BVH Importer (MoCap)",
- "",
- "",
- "",
- aiImporterFlags_SupportTextFlavour,
- 0,
- 0,
- 0,
- 0,
- "bvh"
+ "BVH Importer (MoCap)",
+ "",
+ "",
+ "",
+ aiImporterFlags_SupportTextFlavour,
+ 0,
+ 0,
+ 0,
+ 0,
+ "bvh"
};
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
BVHLoader::BVHLoader()
-: noSkeletonMesh()
+ : mLine(),
+ mAnimTickDuration(),
+ mAnimNumFrames(),
+ noSkeletonMesh()
{}
// ------------------------------------------------------------------------------------------------
@@ -74,461 +83,461 @@ BVHLoader::~BVHLoader()
{}
// ------------------------------------------------------------------------------------------------
-// Returns whether the class can handle the format of the given file.
+// Returns whether the class can handle the format of the given file.
bool BVHLoader::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool cs) const
{
- // check file extension
- const std::string extension = GetExtension(pFile);
-
- if( extension == "bvh")
- return true;
-
- if ((!extension.length() || cs) && pIOHandler) {
- const char* tokens[] = {"HIERARCHY"};
- return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1);
- }
- return false;
+ // check file extension
+ const std::string extension = GetExtension(pFile);
+
+ if( extension == "bvh")
+ return true;
+
+ if ((!extension.length() || cs) && pIOHandler) {
+ const char* tokens[] = {"HIERARCHY"};
+ return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1);
+ }
+ return false;
}
// ------------------------------------------------------------------------------------------------
void BVHLoader::SetupProperties(const Importer* pImp)
{
- noSkeletonMesh = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_NO_SKELETON_MESHES,0) != 0;
+ noSkeletonMesh = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_NO_SKELETON_MESHES,0) != 0;
}
// ------------------------------------------------------------------------------------------------
// Loader meta information
const aiImporterDesc* BVHLoader::GetInfo () const
{
- return &desc;
+ return &desc;
}
// ------------------------------------------------------------------------------------------------
-// Imports the given file into the given scene structure.
+// Imports the given file into the given scene structure.
void BVHLoader::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler)
{
- mFileName = pFile;
+ mFileName = pFile;
- // read file into memory
- boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile));
- if( file.get() == NULL)
- throw DeadlyImportError( "Failed to open file " + pFile + ".");
+ // read file into memory
+ std::unique_ptr<IOStream> file( pIOHandler->Open( pFile));
+ if( file.get() == NULL)
+ throw DeadlyImportError( "Failed to open file " + pFile + ".");
- size_t fileSize = file->FileSize();
- if( fileSize == 0)
- throw DeadlyImportError( "File is too small.");
+ size_t fileSize = file->FileSize();
+ if( fileSize == 0)
+ throw DeadlyImportError( "File is too small.");
- mBuffer.resize( fileSize);
- file->Read( &mBuffer.front(), 1, fileSize);
+ mBuffer.resize( fileSize);
+ file->Read( &mBuffer.front(), 1, fileSize);
- // start reading
- mReader = mBuffer.begin();
- mLine = 1;
- ReadStructure( pScene);
+ // start reading
+ mReader = mBuffer.begin();
+ mLine = 1;
+ ReadStructure( pScene);
- if (!noSkeletonMesh) {
- // build a dummy mesh for the skeleton so that we see something at least
- SkeletonMeshBuilder meshBuilder( pScene);
- }
+ if (!noSkeletonMesh) {
+ // build a dummy mesh for the skeleton so that we see something at least
+ SkeletonMeshBuilder meshBuilder( pScene);
+ }
- // construct an animation from all the motion data we read
- CreateAnimation( pScene);
+ // construct an animation from all the motion data we read
+ CreateAnimation( pScene);
}
// ------------------------------------------------------------------------------------------------
// Reads the file
void BVHLoader::ReadStructure( aiScene* pScene)
{
- // first comes hierarchy
- std::string header = GetNextToken();
- if( header != "HIERARCHY")
- ThrowException( "Expected header string \"HIERARCHY\".");
- ReadHierarchy( pScene);
-
- // then comes the motion data
- std::string motion = GetNextToken();
- if( motion != "MOTION")
- ThrowException( "Expected beginning of motion data \"MOTION\".");
- ReadMotion( pScene);
+ // first comes hierarchy
+ std::string header = GetNextToken();
+ if( header != "HIERARCHY")
+ ThrowException( "Expected header string \"HIERARCHY\".");
+ ReadHierarchy( pScene);
+
+ // then comes the motion data
+ std::string motion = GetNextToken();
+ if( motion != "MOTION")
+ ThrowException( "Expected beginning of motion data \"MOTION\".");
+ ReadMotion( pScene);
}
// ------------------------------------------------------------------------------------------------
// Reads the hierarchy
void BVHLoader::ReadHierarchy( aiScene* pScene)
{
- std::string root = GetNextToken();
- if( root != "ROOT")
- ThrowException( "Expected root node \"ROOT\".");
+ std::string root = GetNextToken();
+ if( root != "ROOT")
+ ThrowException( "Expected root node \"ROOT\".");
- // Go read the hierarchy from here
- pScene->mRootNode = ReadNode();
+ // Go read the hierarchy from here
+ pScene->mRootNode = ReadNode();
}
// ------------------------------------------------------------------------------------------------
// Reads a node and recursively its childs and returns the created node;
aiNode* BVHLoader::ReadNode()
{
- // first token is name
- std::string nodeName = GetNextToken();
- if( nodeName.empty() || nodeName == "{")
- ThrowException( boost::str( boost::format( "Expected node name, but found \"%s\".") % nodeName));
-
- // then an opening brace should follow
- std::string openBrace = GetNextToken();
- if( openBrace != "{")
- ThrowException( boost::str( boost::format( "Expected opening brace \"{\", but found \"%s\".") % openBrace));
-
- // Create a node
- aiNode* node = new aiNode( nodeName);
- std::vector<aiNode*> childNodes;
-
- // and create an bone entry for it
- mNodes.push_back( Node( node));
- Node& internNode = mNodes.back();
-
- // now read the node's contents
- while( 1)
- {
- std::string token = GetNextToken();
-
- // node offset to parent node
- if( token == "OFFSET")
- ReadNodeOffset( node);
- else if( token == "CHANNELS")
- ReadNodeChannels( internNode);
- else if( token == "JOINT")
- {
- // child node follows
- aiNode* child = ReadNode();
- child->mParent = node;
- childNodes.push_back( child);
- }
- else if( token == "End")
- {
- // The real symbol is "End Site". Second part comes in a separate token
- std::string siteToken = GetNextToken();
- if( siteToken != "Site")
- ThrowException( boost::str( boost::format( "Expected \"End Site\" keyword, but found \"%s %s\".") % token % siteToken));
-
- aiNode* child = ReadEndSite( nodeName);
- child->mParent = node;
- childNodes.push_back( child);
- }
- else if( token == "}")
- {
- // we're done with that part of the hierarchy
- break;
- } else
- {
- // everything else is a parse error
- ThrowException( boost::str( boost::format( "Unknown keyword \"%s\".") % token));
- }
- }
-
- // add the child nodes if there are any
- if( childNodes.size() > 0)
- {
- node->mNumChildren = childNodes.size();
- node->mChildren = new aiNode*[node->mNumChildren];
- std::copy( childNodes.begin(), childNodes.end(), node->mChildren);
- }
-
- // and return the sub-hierarchy we built here
- return node;
+ // first token is name
+ std::string nodeName = GetNextToken();
+ if( nodeName.empty() || nodeName == "{")
+ ThrowException( format() << "Expected node name, but found \"" << nodeName << "\"." );
+
+ // then an opening brace should follow
+ std::string openBrace = GetNextToken();
+ if( openBrace != "{")
+ ThrowException( format() << "Expected opening brace \"{\", but found \"" << openBrace << "\"." );
+
+ // Create a node
+ aiNode* node = new aiNode( nodeName);
+ std::vector<aiNode*> childNodes;
+
+ // and create an bone entry for it
+ mNodes.push_back( Node( node));
+ Node& internNode = mNodes.back();
+
+ // now read the node's contents
+ while( 1)
+ {
+ std::string token = GetNextToken();
+
+ // node offset to parent node
+ if( token == "OFFSET")
+ ReadNodeOffset( node);
+ else if( token == "CHANNELS")
+ ReadNodeChannels( internNode);
+ else if( token == "JOINT")
+ {
+ // child node follows
+ aiNode* child = ReadNode();
+ child->mParent = node;
+ childNodes.push_back( child);
+ }
+ else if( token == "End")
+ {
+ // The real symbol is "End Site". Second part comes in a separate token
+ std::string siteToken = GetNextToken();
+ if( siteToken != "Site")
+ ThrowException( format() << "Expected \"End Site\" keyword, but found \"" << token << " " << siteToken << "\"." );
+
+ aiNode* child = ReadEndSite( nodeName);
+ child->mParent = node;
+ childNodes.push_back( child);
+ }
+ else if( token == "}")
+ {
+ // we're done with that part of the hierarchy
+ break;
+ } else
+ {
+ // everything else is a parse error
+ ThrowException( format() << "Unknown keyword \"" << token << "\"." );
+ }
+ }
+
+ // add the child nodes if there are any
+ if( childNodes.size() > 0)
+ {
+ node->mNumChildren = childNodes.size();
+ node->mChildren = new aiNode*[node->mNumChildren];
+ std::copy( childNodes.begin(), childNodes.end(), node->mChildren);
+ }
+
+ // and return the sub-hierarchy we built here
+ return node;
}
// ------------------------------------------------------------------------------------------------
// Reads an end node and returns the created node.
aiNode* BVHLoader::ReadEndSite( const std::string& pParentName)
{
- // check opening brace
- std::string openBrace = GetNextToken();
- if( openBrace != "{")
- ThrowException( boost::str( boost::format( "Expected opening brace \"{\", but found \"%s\".") % openBrace));
-
- // Create a node
- aiNode* node = new aiNode( "EndSite_" + pParentName);
-
- // now read the node's contents. Only possible entry is "OFFSET"
- while( 1)
- {
- std::string token = GetNextToken();
-
- // end node's offset
- if( token == "OFFSET")
- {
- ReadNodeOffset( node);
- }
- else if( token == "}")
- {
- // we're done with the end node
- break;
- } else
- {
- // everything else is a parse error
- ThrowException( boost::str( boost::format( "Unknown keyword \"%s\".") % token));
- }
- }
-
- // and return the sub-hierarchy we built here
- return node;
+ // check opening brace
+ std::string openBrace = GetNextToken();
+ if( openBrace != "{")
+ ThrowException( format() << "Expected opening brace \"{\", but found \"" << openBrace << "\".");
+
+ // Create a node
+ aiNode* node = new aiNode( "EndSite_" + pParentName);
+
+ // now read the node's contents. Only possible entry is "OFFSET"
+ while( 1)
+ {
+ std::string token = GetNextToken();
+
+ // end node's offset
+ if( token == "OFFSET")
+ {
+ ReadNodeOffset( node);
+ }
+ else if( token == "}")
+ {
+ // we're done with the end node
+ break;
+ } else
+ {
+ // everything else is a parse error
+ ThrowException( format() << "Unknown keyword \"" << token << "\"." );
+ }
+ }
+
+ // and return the sub-hierarchy we built here
+ return node;
}
// ------------------------------------------------------------------------------------------------
// Reads a node offset for the given node
void BVHLoader::ReadNodeOffset( aiNode* pNode)
{
- // Offset consists of three floats to read
- aiVector3D offset;
- offset.x = GetNextTokenAsFloat();
- offset.y = GetNextTokenAsFloat();
- offset.z = GetNextTokenAsFloat();
-
- // build a transformation matrix from it
- pNode->mTransformation = aiMatrix4x4( 1.0f, 0.0f, 0.0f, offset.x, 0.0f, 1.0f, 0.0f, offset.y,
- 0.0f, 0.0f, 1.0f, offset.z, 0.0f, 0.0f, 0.0f, 1.0f);
+ // Offset consists of three floats to read
+ aiVector3D offset;
+ offset.x = GetNextTokenAsFloat();
+ offset.y = GetNextTokenAsFloat();
+ offset.z = GetNextTokenAsFloat();
+
+ // build a transformation matrix from it
+ pNode->mTransformation = aiMatrix4x4( 1.0f, 0.0f, 0.0f, offset.x, 0.0f, 1.0f, 0.0f, offset.y,
+ 0.0f, 0.0f, 1.0f, offset.z, 0.0f, 0.0f, 0.0f, 1.0f);
}
// ------------------------------------------------------------------------------------------------
// Reads the animation channels for the given node
void BVHLoader::ReadNodeChannels( BVHLoader::Node& pNode)
{
- // number of channels. Use the float reader because we're lazy
- float numChannelsFloat = GetNextTokenAsFloat();
- unsigned int numChannels = (unsigned int) numChannelsFloat;
-
- for( unsigned int a = 0; a < numChannels; a++)
- {
- std::string channelToken = GetNextToken();
-
- if( channelToken == "Xposition")
- pNode.mChannels.push_back( Channel_PositionX);
- else if( channelToken == "Yposition")
- pNode.mChannels.push_back( Channel_PositionY);
- else if( channelToken == "Zposition")
- pNode.mChannels.push_back( Channel_PositionZ);
- else if( channelToken == "Xrotation")
- pNode.mChannels.push_back( Channel_RotationX);
- else if( channelToken == "Yrotation")
- pNode.mChannels.push_back( Channel_RotationY);
- else if( channelToken == "Zrotation")
- pNode.mChannels.push_back( Channel_RotationZ);
- else
- ThrowException( boost::str( boost::format( "Invalid channel specifier \"%s\".") % channelToken));
- }
+ // number of channels. Use the float reader because we're lazy
+ float numChannelsFloat = GetNextTokenAsFloat();
+ unsigned int numChannels = (unsigned int) numChannelsFloat;
+
+ for( unsigned int a = 0; a < numChannels; a++)
+ {
+ std::string channelToken = GetNextToken();
+
+ if( channelToken == "Xposition")
+ pNode.mChannels.push_back( Channel_PositionX);
+ else if( channelToken == "Yposition")
+ pNode.mChannels.push_back( Channel_PositionY);
+ else if( channelToken == "Zposition")
+ pNode.mChannels.push_back( Channel_PositionZ);
+ else if( channelToken == "Xrotation")
+ pNode.mChannels.push_back( Channel_RotationX);
+ else if( channelToken == "Yrotation")
+ pNode.mChannels.push_back( Channel_RotationY);
+ else if( channelToken == "Zrotation")
+ pNode.mChannels.push_back( Channel_RotationZ);
+ else
+ ThrowException( format() << "Invalid channel specifier \"" << channelToken << "\"." );
+ }
}
// ------------------------------------------------------------------------------------------------
// Reads the motion data
void BVHLoader::ReadMotion( aiScene* /*pScene*/)
{
- // Read number of frames
- std::string tokenFrames = GetNextToken();
- if( tokenFrames != "Frames:")
- ThrowException( boost::str( boost::format( "Expected frame count \"Frames:\", but found \"%s\".") % tokenFrames));
-
- float numFramesFloat = GetNextTokenAsFloat();
- mAnimNumFrames = (unsigned int) numFramesFloat;
-
- // Read frame duration
- std::string tokenDuration1 = GetNextToken();
- std::string tokenDuration2 = GetNextToken();
- if( tokenDuration1 != "Frame" || tokenDuration2 != "Time:")
- ThrowException( boost::str( boost::format( "Expected frame duration \"Frame Time:\", but found \"%s %s\".") % tokenDuration1 % tokenDuration2));
-
- mAnimTickDuration = GetNextTokenAsFloat();
-
- // resize value vectors for each node
- for( std::vector<Node>::iterator it = mNodes.begin(); it != mNodes.end(); ++it)
- it->mChannelValues.reserve( it->mChannels.size() * mAnimNumFrames);
-
- // now read all the data and store it in the corresponding node's value vector
- for( unsigned int frame = 0; frame < mAnimNumFrames; ++frame)
- {
- // on each line read the values for all nodes
- for( std::vector<Node>::iterator it = mNodes.begin(); it != mNodes.end(); ++it)
- {
- // get as many values as the node has channels
- for( unsigned int c = 0; c < it->mChannels.size(); ++c)
- it->mChannelValues.push_back( GetNextTokenAsFloat());
- }
-
- // after one frame worth of values for all nodes there should be a newline, but we better don't rely on it
- }
+ // Read number of frames
+ std::string tokenFrames = GetNextToken();
+ if( tokenFrames != "Frames:")
+ ThrowException( format() << "Expected frame count \"Frames:\", but found \"" << tokenFrames << "\".");
+
+ float numFramesFloat = GetNextTokenAsFloat();
+ mAnimNumFrames = (unsigned int) numFramesFloat;
+
+ // Read frame duration
+ std::string tokenDuration1 = GetNextToken();
+ std::string tokenDuration2 = GetNextToken();
+ if( tokenDuration1 != "Frame" || tokenDuration2 != "Time:")
+ ThrowException( format() << "Expected frame duration \"Frame Time:\", but found \"" << tokenDuration1 << " " << tokenDuration2 << "\"." );
+
+ mAnimTickDuration = GetNextTokenAsFloat();
+
+ // resize value vectors for each node
+ for( std::vector<Node>::iterator it = mNodes.begin(); it != mNodes.end(); ++it)
+ it->mChannelValues.reserve( it->mChannels.size() * mAnimNumFrames);
+
+ // now read all the data and store it in the corresponding node's value vector
+ for( unsigned int frame = 0; frame < mAnimNumFrames; ++frame)
+ {
+ // on each line read the values for all nodes
+ for( std::vector<Node>::iterator it = mNodes.begin(); it != mNodes.end(); ++it)
+ {
+ // get as many values as the node has channels
+ for( unsigned int c = 0; c < it->mChannels.size(); ++c)
+ it->mChannelValues.push_back( GetNextTokenAsFloat());
+ }
+
+ // after one frame worth of values for all nodes there should be a newline, but we better don't rely on it
+ }
}
// ------------------------------------------------------------------------------------------------
// Retrieves the next token
std::string BVHLoader::GetNextToken()
{
- // skip any preceeding whitespace
- while( mReader != mBuffer.end())
- {
- if( !isspace( *mReader))
- break;
-
- // count lines
- if( *mReader == '\n')
- mLine++;
-
- ++mReader;
- }
-
- // collect all chars till the next whitespace. BVH is easy in respect to that.
- std::string token;
- while( mReader != mBuffer.end())
- {
- if( isspace( *mReader))
- break;
-
- token.push_back( *mReader);
- ++mReader;
-
- // little extra logic to make sure braces are counted correctly
- if( token == "{" || token == "}")
- break;
- }
-
- // empty token means end of file, which is just fine
- return token;
+ // skip any preceding whitespace
+ while( mReader != mBuffer.end())
+ {
+ if( !isspace( *mReader))
+ break;
+
+ // count lines
+ if( *mReader == '\n')
+ mLine++;
+
+ ++mReader;
+ }
+
+ // collect all chars till the next whitespace. BVH is easy in respect to that.
+ std::string token;
+ while( mReader != mBuffer.end())
+ {
+ if( isspace( *mReader))
+ break;
+
+ token.push_back( *mReader);
+ ++mReader;
+
+ // little extra logic to make sure braces are counted correctly
+ if( token == "{" || token == "}")
+ break;
+ }
+
+ // empty token means end of file, which is just fine
+ return token;
}
// ------------------------------------------------------------------------------------------------
// Reads the next token as a float
float BVHLoader::GetNextTokenAsFloat()
{
- std::string token = GetNextToken();
- if( token.empty())
- ThrowException( "Unexpected end of file while trying to read a float");
+ std::string token = GetNextToken();
+ if( token.empty())
+ ThrowException( "Unexpected end of file while trying to read a float");
- // check if the float is valid by testing if the atof() function consumed every char of the token
- const char* ctoken = token.c_str();
- float result = 0.0f;
- ctoken = fast_atoreal_move<float>( ctoken, result);
+ // check if the float is valid by testing if the atof() function consumed every char of the token
+ const char* ctoken = token.c_str();
+ float result = 0.0f;
+ ctoken = fast_atoreal_move<float>( ctoken, result);
- if( ctoken != token.c_str() + token.length())
- ThrowException( boost::str( boost::format( "Expected a floating point number, but found \"%s\".") % token));
+ if( ctoken != token.c_str() + token.length())
+ ThrowException( format() << "Expected a floating point number, but found \"" << token << "\"." );
- return result;
+ return result;
}
// ------------------------------------------------------------------------------------------------
// Aborts the file reading with an exception
-void BVHLoader::ThrowException( const std::string& pError)
+AI_WONT_RETURN void BVHLoader::ThrowException( const std::string& pError)
{
- throw DeadlyImportError( boost::str( boost::format( "%s:%d - %s") % mFileName % mLine % pError));
+ throw DeadlyImportError( format() << mFileName << ":" << mLine << " - " << pError);
}
// ------------------------------------------------------------------------------------------------
// Constructs an animation for the motion data and stores it in the given scene
void BVHLoader::CreateAnimation( aiScene* pScene)
{
- // create the animation
- pScene->mNumAnimations = 1;
- pScene->mAnimations = new aiAnimation*[1];
- aiAnimation* anim = new aiAnimation;
- pScene->mAnimations[0] = anim;
-
- // put down the basic parameters
- anim->mName.Set( "Motion");
- anim->mTicksPerSecond = 1.0 / double( mAnimTickDuration);
- anim->mDuration = double( mAnimNumFrames - 1);
-
- // now generate the tracks for all nodes
- anim->mNumChannels = mNodes.size();
- anim->mChannels = new aiNodeAnim*[anim->mNumChannels];
-
- // FIX: set the array elements to NULL to ensure proper deletion if an exception is thrown
- for (unsigned int i = 0; i < anim->mNumChannels;++i)
- anim->mChannels[i] = NULL;
-
- for( unsigned int a = 0; a < anim->mNumChannels; a++)
- {
- const Node& node = mNodes[a];
- const std::string nodeName = std::string( node.mNode->mName.data );
- aiNodeAnim* nodeAnim = new aiNodeAnim;
- anim->mChannels[a] = nodeAnim;
- nodeAnim->mNodeName.Set( nodeName);
-
- // translational part, if given
- if( node.mChannels.size() == 6)
- {
- nodeAnim->mNumPositionKeys = mAnimNumFrames;
- nodeAnim->mPositionKeys = new aiVectorKey[mAnimNumFrames];
- aiVectorKey* poskey = nodeAnim->mPositionKeys;
- for( unsigned int fr = 0; fr < mAnimNumFrames; ++fr)
- {
- poskey->mTime = double( fr);
-
- // Now compute all translations in the right order
- for( unsigned int channel = 0; channel < 3; ++channel)
- {
- switch( node.mChannels[channel])
- {
- case Channel_PositionX: poskey->mValue.x = node.mChannelValues[fr * node.mChannels.size() + channel]; break;
- case Channel_PositionY: poskey->mValue.y = node.mChannelValues[fr * node.mChannels.size() + channel]; break;
- case Channel_PositionZ: poskey->mValue.z = node.mChannelValues[fr * node.mChannels.size() + channel]; break;
- default: throw DeadlyImportError( "Unexpected animation channel setup at node " + nodeName );
- }
- }
- ++poskey;
- }
- } else
- {
- // if no translation part is given, put a default sequence
- aiVector3D nodePos( node.mNode->mTransformation.a4, node.mNode->mTransformation.b4, node.mNode->mTransformation.c4);
- nodeAnim->mNumPositionKeys = 1;
- nodeAnim->mPositionKeys = new aiVectorKey[1];
- nodeAnim->mPositionKeys[0].mTime = 0.0;
- nodeAnim->mPositionKeys[0].mValue = nodePos;
- }
-
- // rotation part. Always present. First find value offsets
- {
- unsigned int rotOffset = 0;
- if( node.mChannels.size() == 6)
- {
- // Offset all further calculations
- rotOffset = 3;
- }
-
- // Then create the number of rotation keys
- nodeAnim->mNumRotationKeys = mAnimNumFrames;
- nodeAnim->mRotationKeys = new aiQuatKey[mAnimNumFrames];
- aiQuatKey* rotkey = nodeAnim->mRotationKeys;
- for( unsigned int fr = 0; fr < mAnimNumFrames; ++fr)
- {
- aiMatrix4x4 temp;
- aiMatrix3x3 rotMatrix;
-
- for( unsigned int channel = 0; channel < 3; ++channel)
- {
- // translate ZXY euler angels into a quaternion
- const float angle = node.mChannelValues[fr * node.mChannels.size() + rotOffset + channel] * float( AI_MATH_PI) / 180.0f;
-
- // Compute rotation transformations in the right order
- switch (node.mChannels[rotOffset+channel])
- {
- case Channel_RotationX: aiMatrix4x4::RotationX( angle, temp); rotMatrix *= aiMatrix3x3( temp); break;
- case Channel_RotationY: aiMatrix4x4::RotationY( angle, temp); rotMatrix *= aiMatrix3x3( temp); break;
- case Channel_RotationZ: aiMatrix4x4::RotationZ( angle, temp); rotMatrix *= aiMatrix3x3( temp); break;
- default: throw DeadlyImportError( "Unexpected animation channel setup at node " + nodeName );
- }
- }
-
- rotkey->mTime = double( fr);
- rotkey->mValue = aiQuaternion( rotMatrix);
- ++rotkey;
- }
- }
-
- // scaling part. Always just a default track
- {
- nodeAnim->mNumScalingKeys = 1;
- nodeAnim->mScalingKeys = new aiVectorKey[1];
- nodeAnim->mScalingKeys[0].mTime = 0.0;
- nodeAnim->mScalingKeys[0].mValue.Set( 1.0f, 1.0f, 1.0f);
- }
- }
+ // create the animation
+ pScene->mNumAnimations = 1;
+ pScene->mAnimations = new aiAnimation*[1];
+ aiAnimation* anim = new aiAnimation;
+ pScene->mAnimations[0] = anim;
+
+ // put down the basic parameters
+ anim->mName.Set( "Motion");
+ anim->mTicksPerSecond = 1.0 / double( mAnimTickDuration);
+ anim->mDuration = double( mAnimNumFrames - 1);
+
+ // now generate the tracks for all nodes
+ anim->mNumChannels = mNodes.size();
+ anim->mChannels = new aiNodeAnim*[anim->mNumChannels];
+
+ // FIX: set the array elements to NULL to ensure proper deletion if an exception is thrown
+ for (unsigned int i = 0; i < anim->mNumChannels;++i)
+ anim->mChannels[i] = NULL;
+
+ for( unsigned int a = 0; a < anim->mNumChannels; a++)
+ {
+ const Node& node = mNodes[a];
+ const std::string nodeName = std::string( node.mNode->mName.data );
+ aiNodeAnim* nodeAnim = new aiNodeAnim;
+ anim->mChannels[a] = nodeAnim;
+ nodeAnim->mNodeName.Set( nodeName);
+
+ // translational part, if given
+ if( node.mChannels.size() == 6)
+ {
+ nodeAnim->mNumPositionKeys = mAnimNumFrames;
+ nodeAnim->mPositionKeys = new aiVectorKey[mAnimNumFrames];
+ aiVectorKey* poskey = nodeAnim->mPositionKeys;
+ for( unsigned int fr = 0; fr < mAnimNumFrames; ++fr)
+ {
+ poskey->mTime = double( fr);
+
+ // Now compute all translations in the right order
+ for( unsigned int channel = 0; channel < 3; ++channel)
+ {
+ switch( node.mChannels[channel])
+ {
+ case Channel_PositionX: poskey->mValue.x = node.mChannelValues[fr * node.mChannels.size() + channel]; break;
+ case Channel_PositionY: poskey->mValue.y = node.mChannelValues[fr * node.mChannels.size() + channel]; break;
+ case Channel_PositionZ: poskey->mValue.z = node.mChannelValues[fr * node.mChannels.size() + channel]; break;
+ default: throw DeadlyImportError( "Unexpected animation channel setup at node " + nodeName );
+ }
+ }
+ ++poskey;
+ }
+ } else
+ {
+ // if no translation part is given, put a default sequence
+ aiVector3D nodePos( node.mNode->mTransformation.a4, node.mNode->mTransformation.b4, node.mNode->mTransformation.c4);
+ nodeAnim->mNumPositionKeys = 1;
+ nodeAnim->mPositionKeys = new aiVectorKey[1];
+ nodeAnim->mPositionKeys[0].mTime = 0.0;
+ nodeAnim->mPositionKeys[0].mValue = nodePos;
+ }
+
+ // rotation part. Always present. First find value offsets
+ {
+ unsigned int rotOffset = 0;
+ if( node.mChannels.size() == 6)
+ {
+ // Offset all further calculations
+ rotOffset = 3;
+ }
+
+ // Then create the number of rotation keys
+ nodeAnim->mNumRotationKeys = mAnimNumFrames;
+ nodeAnim->mRotationKeys = new aiQuatKey[mAnimNumFrames];
+ aiQuatKey* rotkey = nodeAnim->mRotationKeys;
+ for( unsigned int fr = 0; fr < mAnimNumFrames; ++fr)
+ {
+ aiMatrix4x4 temp;
+ aiMatrix3x3 rotMatrix;
+
+ for( unsigned int channel = 0; channel < 3; ++channel)
+ {
+ // translate ZXY euler angels into a quaternion
+ const float angle = node.mChannelValues[fr * node.mChannels.size() + rotOffset + channel] * float( AI_MATH_PI) / 180.0f;
+
+ // Compute rotation transformations in the right order
+ switch (node.mChannels[rotOffset+channel])
+ {
+ case Channel_RotationX: aiMatrix4x4::RotationX( angle, temp); rotMatrix *= aiMatrix3x3( temp); break;
+ case Channel_RotationY: aiMatrix4x4::RotationY( angle, temp); rotMatrix *= aiMatrix3x3( temp); break;
+ case Channel_RotationZ: aiMatrix4x4::RotationZ( angle, temp); rotMatrix *= aiMatrix3x3( temp); break;
+ default: throw DeadlyImportError( "Unexpected animation channel setup at node " + nodeName );
+ }
+ }
+
+ rotkey->mTime = double( fr);
+ rotkey->mValue = aiQuaternion( rotMatrix);
+ ++rotkey;
+ }
+ }
+
+ // scaling part. Always just a default track
+ {
+ nodeAnim->mNumScalingKeys = 1;
+ nodeAnim->mScalingKeys = new aiVectorKey[1];
+ nodeAnim->mScalingKeys[0].mTime = 0.0;
+ nodeAnim->mScalingKeys[0].mValue.Set( 1.0f, 1.0f, 1.0f);
+ }
+ }
}
#endif // !! ASSIMP_BUILD_NO_BVH_IMPORTER