Exemplo n.º 1
0
//////////////////////////////////////////////////////////////////////////
// loadJsonFile
BcBool CsPackageImporter::loadJsonFile( const BcChar* pFileName, Json::Value& Root )
{
	BcBool Success = BcFalse;
	BcFile File;
	if( File.open( pFileName ) )
	{
		const BcU8* pData = File.readAllBytes();		
		Json::Reader Reader;
		
		if( Reader.parse( (const char*)pData, (const char*)pData + File.size(), Root ) )
		{
			Success = BcTrue;
		}
		else
		{
			PSY_LOG( "Failed to parse Json:\n %s\n", Reader.getFormatedErrorMessages().c_str() );
 			BcAssertMsg( BcFalse, "Failed to parse \"%s\", see log for more details.", pFileName );
		}
		
		BcMemFree( (void*)pData );
	}
	else
	{
		BcAssertMsg( BcFalse, "Failed to load \"%s\"", pFileName );
	}
	
	return Success;
}
Exemplo n.º 2
0
//////////////////////////////////////////////////////////////////////////
// saveDependancy
void CsCore::saveDependancies( const BcPath& FileName )
{
	BcPath DependanciesFileName( FileName );
	
	// Append new extension.
	DependanciesFileName.append( ".dep" );
	
	// 
	Json::Value Object( Json::arrayValue );

	if( DependancyMap_.find( *FileName ) != DependancyMap_.end() )
	{
		CsDependancyList& DependancyList = DependancyMap_[ *FileName ];
	
		for( CsDependancyListIterator It( DependancyList.begin() ); It != DependancyList.end(); ++It )
		{
			Object.append( saveDependancy( (*It) ) );
		}
	}

	// Output using styled writer.
	Json::StyledWriter Writer;
	std::string JsonOutput = Writer.write( Object );

	BcFile OutFile;
	if( OutFile.open( (*DependanciesFileName).c_str(), bcFM_WRITE ) )
	{
		OutFile.write( JsonOutput.c_str(), JsonOutput.size() );
		OutFile.close();
	}
}
Exemplo n.º 3
0
//////////////////////////////////////////////////////////////////////////
// parseJsonFile
BcBool CsCore::parseJsonFile( const BcChar* pFileName, Json::Value& Root )
{
	BcBool Success = BcFalse;
	BcFile File;
	if( File.open( pFileName ) )
	{
		char* pData = new char[ File.size() ];
		File.read( pData, File.size() );
		
		Json::Reader Reader;
		
		if( Reader.parse( pData, pData + File.size(), Root ) )
		{
			Success = BcTrue;

			// Add file for monitoring.
			FsCore::pImpl()->addFileMonitor( pFileName );
		}
		else
		{
			BcPrintf( "CsCore: Failed to parse Json:\n %s\n", Reader.getFormatedErrorMessages().c_str() );
		}
		
		delete [] pData;
	}
	
	return Success;
}
Exemplo n.º 4
0
//////////////////////////////////////////////////////////////////////////
// Gets a plain text file
std::string DsTemplate::loadTemplateFile( std::string filename )
{
    BcFile file;
    std::string f = filename;
    file.open( f.c_str() );
    // PSY_LOG("Loading file: %s (size: %d)\n", filename.c_str(), file.size());
    if ( !file.isOpen() )
        return "";
    char* data = new char[file.size() + 1];

    BcMemZero(data, file.size() + 1);
    file.read(data, file.size());
    std::string output = data;
    delete data;
    return output;
}
Exemplo n.º 5
0
//////////////////////////////////////////////////////////////////////////
// loadDependancies
void CsCore::loadDependancies( const BcPath& FileName )
{
	BcPath DependanciesFileName( FileName );
	
	// Append new extension.
	DependanciesFileName.append( ".dep" );

	// Overwrite old dependancy list.
	DependancyMap_[ *FileName ] = CsDependancyList();


	// Open dependancy file.
	BcFile OutFile;
	if( OutFile.open( (*DependanciesFileName).c_str(), bcFM_READ ) )
	{
		BcU32 BufferSize = OutFile.size() + 1;
		BcChar* pJsonData = new BcChar[ BufferSize ];
		BcMemZero( pJsonData, BufferSize );
		OutFile.read( pJsonData, OutFile.size() );

		Json::Value Root;
		Json::Reader JsonReader;
		if( JsonReader.parse( pJsonData, pJsonData + OutFile.size(), Root ) )
		{
			// Create a new dependancy list.
			CsDependancyList DependancyList;

			// Iterate over all dependancies for file and parse.
			for( Json::Value::iterator It( Root.begin() ); It != Root.end(); ++It )
			{
				const Json::Value& Value = (*It);
				CsDependancy Dependancy = loadDependancy( Value );
				DependancyList.push_back( Dependancy );
			}

			// Assign.
			DependancyMap_[ *FileName ] = DependancyList;
		}

		OutFile.close();
	}
}
Exemplo n.º 6
0
//////////////////////////////////////////////////////////////////////////
// load
MdlAnim* MD5AnimLoader::load( const BcChar* FileName, const BcChar* NodeName )
{
	BcFile File;
	BcBool Ret;

	ParseMode_ = PM_MAIN;

	BcU32 iJoint = 0;
	BcU32 iBound = 0;
	BcU32 iFrame = 0;
	BcU32 iAnimComp = 0;

	File.open( FileName );

	BcChar Buffer[1024];
	BcChar Command[1024];
	BcChar* pBuffer;

	// Begin the parsage.
	while( !File.eof() )
	{
		// Parse a line	without	the	spaces at the start	or tabs.
		{
			pBuffer	= &Buffer[0];

			BcChar TheChar = 0;
			BcBool bAtSentence = BcFalse;
			while( TheChar != 10 &&	!File.eof()	)
			{
				File.read( &TheChar, 1 );

				if ( TheChar != '\t' )
				{
					bAtSentence	= BcTrue;
				}

				if ( TheChar != 10 &&
				     TheChar != 13 &&
				     bAtSentence )
				{
					*pBuffer = TheChar;
					++pBuffer;
					Ret	= ( pBuffer < ( Buffer + 1024 ) );
					BcAssert( Ret );
					if( !Ret )
					{
						return NULL;
					}
				}
			}

			// Terminate it.
			*pBuffer = 0;
			++pBuffer;
		}

		sscanf( Buffer, "%s", Command );

		if ( BcStrLength( Buffer ) == 0 )
		{
			Command[ 0 ] = 0;
		}

		switch( ParseMode_ )
		{
		case PM_MAIN:
			{
				if( BcStrCompare( "numJoints", Command ) )
				{
					sscanf( Buffer, "numJoints %u", &nJoints_ );
					
					pJoints_ = new MD5_Joint[ nJoints_ ]; 

					for( BcU32 i = 0; i < nFrames_; ++i )
					{
						pFrames_[ i ].nKeys_ = nJoints_;
						pFrames_[ i ].pKeys_ = new MD5_Joint[ nJoints_ ];
					}
				}
				else if( BcStrCompare( "numFrames", Command ) )
				{
					sscanf( Buffer, "numFrames %u", &nFrames_ );
					nBounds_ = nFrames_;
					
					pFrames_ = new MD5_Frame[ nFrames_ ]; 
					pBounds_ = new MD5_Bound[ nBounds_ ]; 
				}
				else if( BcStrCompare( "frameRate", Command ) )
				{
					sscanf( Buffer, "frameRate %f", &FrameRate_ );
				}
				else if( BcStrCompare( "numAnimatedComponents", Command ) )
				{
					sscanf( Buffer, "numAnimatedComponents %u", &nAnimComponents_ );
					pAnimComponents_ = new BcF32[ nAnimComponents_ ];
				}
				else if( BcStrCompare( "hierarchy", Command ) )
				{
					ParseMode_ = PM_HIERARCHY;
					iJoint = 0;
				}
				else if( BcStrCompare( "bounds", Command ) )
				{
					ParseMode_ = PM_BOUNDS;
					iBound = 0;
				}
				else if( BcStrCompare( "baseframe", Command ) )
				{
					ParseMode_ = PM_BASEFRAME;
					iJoint = 0;
				}
				else if ( BcStrCompare( "frame", Command ) )
				{
					ParseMode_ = PM_FRAME;
					iJoint = 0;
					iAnimComp = 0;
				}
			}
			break;
		
		case PM_HIERARCHY:
			{
				if( BcStrCompare( "}", Command ) )
				{
					ParseMode_ = PM_MAIN;
				}
				else
				{
					BcAssert( iJoint < nJoints_ );
					sscanf( Buffer, "%s %u %u %u", &pJoints_[ iJoint ].Name_[0],
					                               &pJoints_[ iJoint ].ParentID_,
					                               &pJoints_[ iJoint ].AnimMask_,
					                               &pJoints_[ iJoint ].AnimOffset_ );
					++iJoint;
				}
			}
			break;

		case PM_BOUNDS:
			{
				if( BcStrCompare( "}", Command ) )
				{
					ParseMode_ = PM_MAIN;
				}
				else
				{
					BcAssert( iBound < nBounds_ );
					sscanf( Buffer, "( %f %f %f ) ( %f %f %f )", &pBounds_[ iBound ].MinX_,
					                                             &pBounds_[ iBound ].MinY_,
					                                             &pBounds_[ iBound ].MinZ_,
					                                             &pBounds_[ iBound ].MaxX_,
					                                             &pBounds_[ iBound ].MaxY_,
					                                             &pBounds_[ iBound ].MaxZ_ );
					iBound++;
				}
			}
			break;

		case PM_BASEFRAME:
			{
				if( BcStrCompare( "}", Command ) )
				{
					ParseMode_ = PM_MAIN;
				}
				else
				{
					BcAssert( iJoint < nJoints_ );
					sscanf( Buffer, "( %f %f %f ) ( %f %f %f )", &pJoints_[ iJoint ].TX_,
					                                             &pJoints_[ iJoint ].TY_,
					                                             &pJoints_[ iJoint ].TZ_,
					                                             &pJoints_[ iJoint ].QX_,
					                                             &pJoints_[ iJoint ].QY_,
					                                             &pJoints_[ iJoint ].QZ_ );
					iJoint++;
				}
			}
			break;

		case PM_FRAME:
			{
				if( BcStrCompare( "}", Command ) )
				{
					// Setup all joints.
					BcAssert( iFrame < nFrames_ );
					MD5_Frame* pFrame = &pFrames_[ iFrame++ ];

					for( BcU32 i = 0; i < nJoints_; ++i )
					{
						// Copy from base.
						pFrame->pKeys_[ i ] = pJoints_[ i ];

						// Parse from anim data.
						BcF32* pData = &pAnimComponents_[ pFrame->pKeys_[ i ].AnimOffset_ ];
						BcU32 iVal = 0;
						BcU32 AnimMask = pFrame->pKeys_[ i ].AnimMask_;

						if( AnimMask & 1 )
						{
							pFrame->pKeys_[ i ].TX_ = pData[ iVal++ ];
						}

						if( AnimMask & 2 )
						{
							pFrame->pKeys_[ i ].TY_ = pData[ iVal++ ];
						}

						if( AnimMask & 4 )
						{
							pFrame->pKeys_[ i ].TZ_ = pData[ iVal++ ];
						}

						if( AnimMask & 8 )
						{
							pFrame->pKeys_[ i ].QX_ = pData[ iVal++ ];
						}

						if( AnimMask & 16 )
						{
							pFrame->pKeys_[ i ].QY_ = pData[ iVal++ ];
						}

						if( AnimMask & 32 )
						{
							pFrame->pKeys_[ i ].QZ_ = pData[ iVal++ ];
						}
					}

					ParseMode_ = PM_MAIN;
				}
				else
				{
					BcF32 Data[]=
					{
						1e6f,
						1e6f,
						1e6f,
						1e6f,
						1e6f,
						1e6f,
					};

					// NOTE: This may not actually work..
					sscanf( Buffer, "%f %f %f %f %f %f", &Data[0],
					                                     &Data[1],
														 &Data[2],
														 &Data[3],
														 &Data[4],
														 &Data[5] );

					// Parse into array.
					for( BcU32 i = 0; i < 6; ++i )
					{
						if( Data[i] < 1e6f )
						{
							BcAssert( iAnimComp < nAnimComponents_ );
							pAnimComponents_[ iAnimComp ] = Data[i];
							iAnimComp++;
						}
						else
						{
							break;
						}
					}
				}
			}
			break;
		}
	}

	// Create animation.
	MdlAnim* pAnimation = new MdlAnim();

	// Build up all nodes.
	for( BcU32 i = 0; i < nJoints_; ++i )
	{
		MdlAnimNode Node;

		BcStrCopy( Node.Name_, pJoints_[ i ].Name_ );
		if( pJoints_[ i ].ParentID_ != -1 )
		{
			BcStrCopy( Node.Parent_, pJoints_[ pJoints_[ i ].ParentID_ ].Name_ );
		}
		else
		{
			Node.Parent_[ 0 ] = '\0';
		}

		for( BcU32 j = 0; j < nFrames_; ++j )
		{
			MD5_Joint* pJoint = &pFrames_[ j ].pKeys_[ i ];

			MdlAnimKey Key;

			Key.R_.set( pJoint->QX_, pJoint->QY_, pJoint->QZ_, 0.0f );
			Key.S_.set( 1.0f, 1.0f, 1.0f );
			Key.T_.set( pJoint->TX_, pJoint->TY_, pJoint->TZ_ );

			Key.R_.calcFromXYZ();

			Node.KeyList_.push_back( Key );
		}

		pAnimation->addNode( Node );
	}

	// Cleanup
	nJoints_ = 0;
	delete [] pJoints_;
	pJoints_ = NULL;

	nBounds_ = 0;
	delete [] pBounds_;
	pBounds_ = NULL;

	nAnimComponents_ = 0;
	delete [] pAnimComponents_;
	pAnimComponents_ = NULL;

	for( BcU32 i = 0; i < nFrames_; ++i )
	{
		delete [] pFrames_[ i ].pKeys_;
	}

	nFrames_ = 0;
	delete [] pFrames_;
	pFrames_ = NULL;

	//
	/*
	BcMat4d RootTransform;
	RootTransform.identity();
	pRootNode->makeRelativeTransform( RootTransform );
	*/

	return pAnimation;//pRootNode;
}
Exemplo n.º 7
0
////////////////////////////////////////////////////////////////////////////////
// update
eSysStateReturn GaMatchmakingState::main()
{
	BcScopedLock< BcMutex > Lock( Lock_ );
	BcReal Delta = SysKernel::pImpl()->getFrameTime();

	switch( HandshakeState_ )
	{
	case HSS_STUN:
		{
			// Only do once.
			if( MappedHandshakeAddr_ == 0 )
			{
				if( doSTUN() )
				{
					SysID_ = static_cast< BcU32 >( BcHash( (BcU8*)&MappedHandshakeAddr_, sizeof( MappedHandshakeAddr_ ) ) ); // Hash the mapped address to we don't broadcast it.
					if( MappedHandshakeAddr_ != 0 )
					{
						HandshakeState_ = HSS_IDLE;
					}
				}
				else
				{
					HandshakeState_ = HSS_STUN;
				}
			}
			else
			{
				HandshakeState_ = HSS_IDLE;
			}
		}
		break;
	case HSS_IDLE:
		{
			ConnectTimer_ -= Delta;

			if( ConnectTimer_ < 0.0f )
			{
				if( pSession_ == NULL )
				{
					pSession_ = irc_create_session( &Callbacks_ );
				}

				if( pSession_ != NULL && !irc_is_connected( pSession_ ) )
				{
					irc_set_ctx( pSession_, this );

					std::string Channel = "#testchannel";
					BcFile File;
					if( File.open( "config.json" ) )
					{
						char* pData = new char[ File.size() ];
						File.read( pData, File.size() );
						Json::Reader Reader;
		
						Json::Value Root;
						if( Reader.parse( pData, pData + File.size(), Root ) )
						{
							Channel = Root["channel"].asCString();
						}
						delete [] pData;
					}

					BcSPrintf( ScreenName_, "%s_%x", "PSY", BcRandom::Global.rand() );
					BcSPrintf( Channel_, Channel.c_str() );

					// Connect to the server.
					int RetVal = irc_connect( pSession_, "www.neilo.gd", 8000, NULL, ScreenName_, ScreenName_, ScreenName_ );

					if( RetVal == 0 )
					{
						// Start the thread to tick the client.
						BcThread::start( "EvtBridgeIRC" );

						ClientID_ = BcErrorCode;
						RemoteHandshakeAddr_ = 0;
						RemoteHandshakePort_ = 0;
						//LocalHandshakeAddr_ = 0;
						//LocalHandshakePort_ = 0;
						//MappedHandshakeAddr_ = 0;
						//MappedHandshakePort_ = 0;
						HandshakeState_ = HSS_WAIT_INVITE;
					}
					else
					{
						BcThread::join();

						irc_destroy_session( pSession_ );
						pSession_ = NULL;
					}
				}
			}
		}
		break;

	case HSS_WAIT_INVITE:
		{
			InviteTimer_ -= Delta;

			if( InviteTimer_ < 0.0f )
			{
				InviteTimer_ = BcAbs( BcRandom::Global.randReal() ) * 5.0f + 5.0f;

				// Send play with me message to channel.

				BcChar PlayBuffer[256];
				BcSPrintf( PlayBuffer, "REQ:%u", SysID_ );
				irc_cmd_msg( pSession_, Channel_, PlayBuffer );
			}
		}
		break;

	case HSS_WAIT_ADDR:
		{
			HandshakeTimer_ -= Delta;

			if( HandshakeTimer_ < 0.0f )
			{
				HandshakeState_ = HSS_WAIT_INVITE;
			}
		}
		break;

	case HSS_COMPLETE:
		{
			BcPrintf("GaMatchmakingState: Complete! ClientID of ours is %u\n", ClientID_);
			return sysSR_FINISHED;
		}
		break;
	}

	if( HandshakeState_ != HSS_STUN )
	{
		if( HandshakeState_ != HSS_IDLE && ( pSession_ == NULL || !irc_is_connected( pSession_ ) ) )
		{
			BcSleep( 0.1f );
			BcThread::join();
			BcSleep( 0.1f );
			if( pSession_ != NULL )
			{
				irc_destroy_session( pSession_ );
				pSession_ = NULL;
			}
			HandshakeState_ = HSS_IDLE;
			ConnectTimer_ = 10.0f;
		}
	}

	return sysSR_CONTINUE;
}
Exemplo n.º 8
0
//////////////////////////////////////////////////////////////////////////
// load
MdlNode* MD5MeshLoader::load( const BcChar* FileName, const BcChar* NodeName )
{
	BcFile File;
	BcBool Ret;

	ParseMode_ = PM_MAIN;

	BcU32 iJoint = 0;
	BcU32 iMesh = 0;
	BcU32 iVert = 0;
	BcU32 iInd = 0;
	BcU32 iWeight = 0;

	if( File.open( FileName ) == BcFalse )
	{
		return NULL;
	}

	BcChar Buffer[1024];
	BcChar Command[1024];
	BcChar* pBuffer;

	// Begin the parsage.
	while( !File.eof() )
	{
		// Parse a line	without	the	spaces at the start	or tabs.
		{
			pBuffer	= &Buffer[0];

			BcChar TheChar = 0;
			BcBool bAtSentence = BcFalse;
			while( TheChar != 10 &&	!File.eof()	)
			{
				File.read( &TheChar, 1 );

				if ( TheChar != '\t' )
				{
					bAtSentence	= BcTrue;
				}

				if ( TheChar != 10 &&
				     TheChar != 13 &&
				     bAtSentence )
				{
					*pBuffer = TheChar;
					++pBuffer;
					Ret	= ( pBuffer < ( Buffer + 1024 ) );
					BcAssert( Ret );
					if( !Ret )
					{
						return NULL;
					}
				}
			}

			// Terminate it.
			*pBuffer = 0;
			++pBuffer;
		}

		sscanf( Buffer, "%s", Command );

		if ( BcStrLength( Buffer ) == 0 )
		{
			Command[ 0 ] = 0;
		}

		switch( ParseMode_ )
		{
		case PM_MAIN:
			{
				if( BcStrCompare( "numJoints", Command ) )
				{
					sscanf( Buffer, "numJoints %u", &nJoints_ );
					
					pJoints_ = new MD5_Joint[ nJoints_ ]; 
				}
				else if( BcStrCompare( "numMeshes", Command ) )
				{
					sscanf( Buffer, "numMeshes %u", &nMeshes_ );
					
					pMeshes_ = new MD5_Mesh[ nMeshes_ ]; 
				}
				else if( BcStrCompare( "joints", Command ) )
				{
					ParseMode_ = PM_JOINTS;
				}
				else if( BcStrCompare( "mesh", Command ) )
				{
					ParseMode_ = PM_MESH;

					iVert = 0;
					iInd = 0;
					iWeight = 0;
				}
			}
			break;

		case PM_JOINTS:
			{
				if( BcStrCompare( "}", Command ) )
				{
					ParseMode_ = PM_MAIN;
				}
				else
				{
					// Parse a joint off.
					BcAssert( iJoint < nJoints_ );
					MD5_Joint* pJoint = &pJoints_[ iJoint ];
					sscanf( Buffer, "%s %i ( %f %f %f ) ( %f %f %f )", pJoint->Name_, &pJoint->ParentID_, &pJoint->TX_, &pJoint->TY_, &pJoint->TZ_, &pJoint->QX_, &pJoint->QY_, &pJoint->QZ_ );
					++iJoint;
				}
			}
			break;

		case PM_MESH:
			{
				if( BcStrCompare( "}", Command ) )
				{
					++iMesh;
					ParseMode_ = PM_MAIN;
				}
				else
				{
					BcAssert( iMesh < nMeshes_ );
					MD5_Mesh* pMesh = &pMeshes_[ iMesh ];

					if ( BcStrCompare( "shader", Command ) )
					{
						sscanf( Buffer, "shader \"%s", pMesh->Shader_ );
						BcU32 i = BcStrLength( pMesh->Shader_ ) - 1;
						pMesh->Shader_[ i ] = '\0';
					}
					else if ( BcStrCompare( "numverts", Command ) )
					{
						sscanf( Buffer, "numverts %u", &pMesh->nVerts_ );
						pMesh->pVerts_ = new MD5_Vert[ pMesh->nVerts_ ];
					}
					else if ( BcStrCompare( "vert", Command ) )
					{
						// Parse a vert off
						BcAssert( iVert < pMesh->nVerts_ );
						MD5_Vert* pVert = &pMesh->pVerts_[ iVert ];
						sscanf( Buffer, "vert %i ( %f %f ) %i %i", &pVert->Index_, &pVert->U_, &pVert->V_, &pVert->WeightIndex_, &pVert->nWeights_ );
						++iVert;
					}
					else if ( BcStrCompare( "numtris", Command ) )
					{
						sscanf( Buffer, "numtris %u", &pMesh->nIndices_ );
						pMesh->nIndices_ *= 3;
						pMesh->pIndices_ = new BcU32[ pMesh->nIndices_ ];
					}
					else if ( BcStrCompare( "tri", Command ) )
					{
						// Parse a vert off
						BcAssert( iInd < pMesh->nIndices_ );
						BcU32 Index;
						BcU32* pIndex = &pMesh->pIndices_[ iInd ];
						sscanf( Buffer, "tri %i %i %i %i", &Index, &pIndex[0], &pIndex[1], &pIndex[2] );
						iInd += 3;
					}
					else if ( BcStrCompare( "numweights", Command ) )
					{
						sscanf( Buffer, "numweights %u", &pMesh->nWeights_ );
						pMesh->pWeights_ = new MD5_Weight[ pMesh->nWeights_ ];
					}
					else if ( BcStrCompare( "weight", Command ) )
					{
						// Parse a vert off
						BcAssert( iWeight < pMesh->nWeights_ );
						MD5_Weight* pWeight = &pMesh->pWeights_[ iWeight ];
						sscanf( Buffer, "weight %i %i %f ( %f %f %f )", &pWeight->Index_, &pWeight->JointID_, &pWeight->Weight_, &pWeight->X_, &pWeight->Y_, &pWeight->Z_ );
						++iWeight;
					}
				}
			}
			break;
		}
	}

	// Now that we are loaded we can build the node graph.
	MdlNode* pRootNode = new MdlNode();

	pRootNode->name( NodeName );

	for( BcU32 i = 0; i < nMeshes_; ++i )
	{
		buildBindPose( pRootNode, i );
	}

	// Parent joints up.
	//if( nJoints_ > 1 )
	{
		for( BcU32 i = 0; i < nJoints_; ++i )
		{
			MD5_Joint* pJoint = &pJoints_[ i ];
			MdlNode* pNode = new MdlNode();

			pNode->name( pJoint->Name_ );
			pNode->type( eNT_JOINT );

			// Build the transform and inverse bind pose.
			BcQuat JointRot( pJoint->QX_, pJoint->QY_, pJoint->QZ_, 0.0f );
			JointRot.calcFromXYZ();
			BcMat4d JointRotation;
			BcMat4d JointTranslate;
			BcMat4d JointTransform;
			BcMat4d InverseBindpose;
			JointRot.asMatrix4d( JointRotation );
			JointTranslate.identity();
			JointTranslate.row3( BcVec4d( pJoint->TX_, pJoint->TY_, pJoint->TZ_, 1.0f ) );

			JointTransform = JointRotation * JointTranslate;
			InverseBindpose = JointTransform;
			InverseBindpose.inverse();

			pNode->absoluteTransform( JointTransform );
			pNode->inverseBindpose( InverseBindpose );

			if( pJoint->ParentID_ != BcErrorCode )
			{
				pRootNode->parentNode( pNode, pJoints_[ pJoint->ParentID_ ].Name_ );
			}
			else
			{
				// Parent to root.
				pRootNode->parentNode( pNode, pRootNode->name() );
			}
		}
	}

	// Cleanup
	nJoints_ = 0;
	delete [] pJoints_;
	pJoints_ = NULL;

	for( BcU32 i = 0; i < nMeshes_; ++i )
	{
		delete [] pMeshes_[ i ].pIndices_;
		delete [] pMeshes_[ i ].pVerts_;
		delete [] pMeshes_[ i ].pWeights_;
	}

	nMeshes_ = 0;
	delete [] pMeshes_;
	pMeshes_ = NULL;

	//
	BcMat4d RootTransform;
	RootTransform.identity();
	pRootNode->makeRelativeTransform( RootTransform );

	return pRootNode;
}