Refactor: Expand tabs to 4 spaces

This commit is contained in:
Richard
2015-05-18 21:57:13 -06:00
parent a96a595a7a
commit 83de707587
324 changed files with 78951 additions and 78956 deletions

View File

@@ -55,16 +55,16 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
using namespace Assimp;
static const aiImporterDesc desc = {
"BVH Importer (MoCap)",
"",
"",
"",
aiImporterFlags_SupportTextFlavour,
0,
0,
0,
0,
"bvh"
"BVH Importer (MoCap)",
"",
"",
"",
aiImporterFlags_SupportTextFlavour,
0,
0,
0,
0,
"bvh"
};
// ------------------------------------------------------------------------------------------------
@@ -82,458 +82,458 @@ BVHLoader::~BVHLoader()
// 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);
// check file extension
const std::string extension = GetExtension(pFile);
if( extension == "bvh")
return true;
if( extension == "bvh")
return true;
if ((!extension.length() || cs) && pIOHandler) {
const char* tokens[] = {"HIERARCHY"};
return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1);
}
return false;
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.
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
boost::scoped_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);
// 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);
// 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));
// 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));
// 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;
// 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();
// 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();
// 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));
// 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));
}
}
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);
}
// 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;
// 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));
// 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);
// 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();
// 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));
}
}
// 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;
// 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();
// 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);
// 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;
// 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();
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));
}
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));
}
}
// ------------------------------------------------------------------------------------------------
// 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));
// 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;
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));
// 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();
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);
// 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());
}
// 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
}
// 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;
// skip any preceeding whitespace
while( mReader != mBuffer.end())
{
if( !isspace( *mReader))
break;
// count lines
if( *mReader == '\n')
mLine++;
// count lines
if( *mReader == '\n')
mLine++;
++mReader;
}
++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;
// 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;
token.push_back( *mReader);
++mReader;
// little extra logic to make sure braces are counted correctly
if( token == "{" || token == "}")
break;
}
// 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;
// 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( boost::str( boost::format( "Expected a floating point number, but found \"%s\".") % token));
return result;
return result;
}
// ------------------------------------------------------------------------------------------------
// Aborts the file reading with an exception
AI_WONT_RETURN void BVHLoader::ThrowException( const std::string& pError)
{
throw DeadlyImportError( boost::str( boost::format( "%s:%d - %s") % mFileName % mLine % pError));
throw DeadlyImportError( boost::str( boost::format( "%s:%d - %s") % 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;
// 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);
// 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];
// 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;
// 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);
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);
// 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;
}
// 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;
}
// 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;
// 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;
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 );
}
}
// 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;
}
}
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);
}
}
// 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