Esempio n. 1
0
void Tools::DisplayMaterial::DisplayMaterial( FbxGeometry *i_geometry )
{
	DisplayCommon::DisplayString( "\n\n--------------------\nMaterial\n--------------------" );
	int materialCount = 0;
	FbxNode *node = NULL;

	if( i_geometry )
	{
		node = i_geometry->GetNode();
		if( node )
			materialCount = node->GetMaterialCount();
	}

	if( materialCount > 0 )
	{
		FbxPropertyT<FbxDouble3> double3;
		FbxPropertyT<FbxDouble> double1;
		FbxColor theColor;

		for( int ctr = 0; ctr < materialCount; ctr++ )
		{
			DisplayCommon::DisplayInt( "        Material ", ctr );

			FbxSurfaceMaterial *material = node->GetMaterial( ctr );

			DisplayCommon::DisplayString( "            Name: \"", (char *) material->GetName(), "\"" ); 

#ifdef DISPLAY_HARDWARE_SHADER_INFORMATION
			//Get the implementation to see if it's a hardware shader.
			// Note:: this cause memory leak
			const FbxImplementation* implementation = GetImplementation( material, FBXSDK_IMPLEMENTATION_HLSL );
			FbxString implementationType = "HLSL";
			if( !implementation )
			{
				implementation = GetImplementation( material, FBXSDK_IMPLEMENTATION_CGFX );
				implementationType = "CGFX";
			}

			if( implementation )
			{
				//Now we have a hardware shader, let's read it
				FBXSDK_printf( "            Hardware Shader Type: %s\n", implemenationType.Buffer() );
				DisplayCommon::DisplayString( "            Hardware Shader Type: ", implemenationType );

				const FbxBindingTable* rootTable = implementation->GetRootTable();
				FbxString fileName = rootTable->DescAbsoluteURL.Get();
				FbxString techniqueName = rootTable->DescTAG.Get(); 

				const FbxBindingTable* table = implementation->GetRootTable();
				size_t entryNum = table->GetEntryCount();

				for( int i = 0; i < (int)entryNum; i++ )
				{
					const FbxBindingTableEntry& entry = table->GetEntry( i );
					const char *entrySrcType = entry.GetEntryType( true ); 
					FbxProperty fbxProp;

					FbxString test = entry.GetSource();
					FBXSDK_printf( "            Entry: %s\n", test.Buffer() );
					DisplayCommon::DisplayString( "            Entry: %s\n", test );

					if ( strcmp( FbxPropertyEntryView::sEntryType, entrySrcType ) == 0 )
					{
						fbxProp = material->FindPropertyHierarchical(entry.GetSource()); 
						if( !fbxProp.IsValid() )
						{
							fbxProp = material->RootProperty.FindHierarchical( entry.GetSource() );
						}
					}
					else if( strcmp( FbxConstantEntryView::sEntryType, entrySrcType ) == 0 )
					{
						fbxProp = implementation->GetConstants().FindHierarchical( entry.GetSource() );
					}
					if( fbxProp.IsValid() )
					{
						if( fbxProp.GetSrcObjectCount<FbxTexture>() > 0 )
						{
							//do what you want with the textures
							for( int j = 0; j < fbxProp.GetSrcObjectCount<FbxFileTexture>(); j++ )
							{
								FbxFileTexture *tex = fbxProp.GetSrcObject<FbxFileTexture>( j );
								FBXSDK_printf( "           File Texture: %s\n", tex->GetFileName() );
								DisplayCommon::DisplayString( "           File Texture: %s\n", tex->GetFileName() );
							}
							for( int j = 0; j < fbxProp.GetSrcObjectCount<FbxLayeredTexture>(); j++ )
							{
								FbxLayeredTexture *tex = fbxProp.GetSrcObject<FbxLayeredTexture>( j );
								FBXSDK_printf( "        Layered Texture: %s\n", tex->GetName() );
								DisplayCommon::DisplayString( "        Layered Texture: %s\n", tex->GetName() );
							}
							for( int j = 0; j < fbxProp.GetSrcObjectCount<FbxProceduralTexture>(); j++ )
							{
								FbxProceduralTexture *tex = fbxProp.GetSrcObject<FbxProceduralTexture>( j );
								FBXSDK_printf( "     Procedural Texture: %s\n", tex->GetName() );
								DisplayCommon::DisplayString( "     Procedural Texture: %s\n", tex->GetName() );
							}
						}
						else
						{
							FbxDataType fbxType = fbxProp.GetPropertyDataType();
							FbxString fbxName = fbxType.GetName();
							if( FbxBoolDT == fbxType )
							{
								DisplayCommon::DisplayBool( "                Bool: ", fbxProp.Get<FbxBool>() );
							}
							else if( FbxIntDT == fbxType ||  FbxEnumDT  == fbxType )
							{
								DisplayCommon::DisplayInt( "                Int: ", fbxProp.Get<FbxInt>() );
							}
							else if( FbxFloatDT == fbxType )
							{
								DisplayCommon::DisplayDouble( "                Float: ", fbxProp.Get<FbxFloat>() );
							}
							else if( FbxDoubleDT == fbxType )
							{
								DisplayCommon::DisplayDouble( "                Double: ", fbxProp.Get<FbxDouble>() );
							}
							else if( FbxStringDT == fbxType || FbxUrlDT  == fbxType || FbxXRefUrlDT  == fbxType )
							{
								DisplayCommon::DisplayString( "                String: ", fbxProp.Get<FbxString>().Buffer() );
							}
							else if( FbxDouble2DT == fbxType )
							{
								FbxDouble2 double2 = fbxProp.Get<FbxDouble2>();
								FbxVector2 vector;
								vector[0] = double2[0];
								vector[1] = double2[1];
								DisplayCommon::Display2DVector( "                2D vector: ", vector );
							}
							else if( (FbxDouble3DT == fbxType) || (FbxColor3DT == fbxType) )
							{
								FbxDouble3 double3 = fbxProp.Get<FbxDouble3>();
								FbxVector4 vector;
								vector[0] = double3[0];
								vector[1] = double3[1];
								vector[2] = double3[2];
								DisplayCommon::Display3DVector( "                3D vector: ", vector );
							}
							else if( (FbxDouble4DT == fbxType) || (FbxColor4DT == fbxType) )
							{
								FbxDouble4 double4 = fbxProp.Get<FbxDouble4>();
								FbxVector4 vector;
								vector[0] = double4[0];
								vector[1] = double4[1];
								vector[2] = double4[2];
								vector[3] = double4[3];
								DisplayCommon::Display4DVector( "                4D vector: ", vector );
							}
							else if( FbxDouble4x4DT == fbxType )
							{
								FbxDouble4x4 double44 = fbxProp.Get<FbxDouble4x4>();
								for( int j = 0; j < 4; j++ )
								{
									FbxVector4 vector;
									vector[0] = double44[j][0];
									vector[1] = double44[j][1];
									vector[2] = double44[j][2];
									vector[3] = double44[j][3];
									DisplayCommon::Display4DVector( "                4x4D vector: ", vector );
								}
							}
						}
					}
				}
			}
			else
#endif	// #ifdef DISPLAY_HARDWARE_SHADER_INFORMATION
			if( material->GetClassId().Is(FbxSurfacePhong::ClassId) )
			{
				// We found a Phong material.  Display its properties.

				// Display the Ambient Color
				double3 = ((FbxSurfacePhong *) material)->Ambient;
				theColor.Set( double3.Get()[0], double3.Get()[1], double3.Get()[2] );
				DisplayCommon::DisplayColor( "            Ambient: ", theColor );

				// Display the Diffuse Color
				double3 = ((FbxSurfacePhong *) material)->Diffuse;
				theColor.Set( double3.Get()[0], double3.Get()[1], double3.Get()[2] );
				DisplayCommon::DisplayColor( "            Diffuse: ", theColor );

				// Display the Specular Color (unique to Phong materials)
				double3 = ((FbxSurfacePhong *) material)->Specular;
				theColor.Set( double3.Get()[0], double3.Get()[1], double3.Get()[2] );
				DisplayCommon::DisplayColor( "            Specular: ", theColor );

				// Display the Emissive Color
				double3 = ((FbxSurfacePhong *) material)->Emissive;
				theColor.Set( double3.Get()[0], double3.Get()[1], double3.Get()[2] );
				DisplayCommon::DisplayColor( "            Emissive: ", theColor );

				//Opacity is Transparency factor now
				double1 = ((FbxSurfacePhong *) material)->TransparencyFactor;
				DisplayCommon::DisplayDouble( "            Opacity: ", 1.0-double1.Get() );

				// Display the Shininess
				double1 = ((FbxSurfacePhong *) material)->Shininess;
				DisplayCommon::DisplayDouble( "            Shininess: ", double1.Get() );

				// Display the Reflectivity
				double1 = ((FbxSurfacePhong *) material)->ReflectionFactor;
				DisplayCommon::DisplayDouble( "            Reflectivity: ", double1.Get() );
			}
			else if( material->GetClassId().Is(FbxSurfaceLambert::ClassId) )
			{
				// We found a Lambert material. Display its properties.
				// Display the Ambient Color
				double3 = ((FbxSurfaceLambert *)material)->Ambient;
				theColor.Set( double3.Get()[0], double3.Get()[1], double3.Get()[2] );
				DisplayCommon::DisplayColor( "            Ambient: ", theColor );

				// Display the Diffuse Color
				double3 = ((FbxSurfaceLambert *)material)->Diffuse;
				theColor.Set( double3.Get()[0], double3.Get()[1], double3.Get()[2] );
				DisplayCommon::DisplayColor( "            Diffuse: ", theColor );

				// Display the Emissive
				double3 = ((FbxSurfaceLambert *)material)->Emissive;
				theColor.Set( double3.Get()[0], double3.Get()[1], double3.Get()[2] );
				DisplayCommon::DisplayColor( "            Emissive: ", theColor );

				// Display the Opacity
				double1 = ((FbxSurfaceLambert *)material)->TransparencyFactor;
				DisplayCommon::DisplayDouble( "            Opacity: ", 1.0-double1.Get() );
			}
			else
				DisplayCommon::DisplayString( "Unknown type of Material" );

			FbxPropertyT<FbxString> string;
			string = material->ShadingModel;
			DisplayCommon::DisplayString( "            Shading Model: ", string.Get() );
		}
	}
}
Esempio n. 2
0
void Tools::DisplayAnimation::DisplayChannels( FbxNode* i_node, FbxAnimLayer* i_animLayer, void (*DisplayCurve) (FbxAnimCurve* i_curve), void (*DisplayListCurve) (FbxAnimCurve* i_curve, FbxProperty* i_property), bool isSwitcher )
{
	FbxAnimCurve *animCurve = NULL;

	// Display general curves.
	if (!isSwitcher)
	{
		animCurve = i_node->LclTranslation.GetCurve( i_animLayer, FBXSDK_CURVENODE_COMPONENT_X );
		if( animCurve )
		{
			FBXSDK_printf( "        TX\n" );
			DisplayCommon::DisplayString( "        TX" );
			DisplayCurve( animCurve );
		}
		animCurve = i_node->LclTranslation.GetCurve( i_animLayer, FBXSDK_CURVENODE_COMPONENT_Y );
		if( animCurve )
		{
			FBXSDK_printf( "        TY\n" );
			DisplayCommon::DisplayString( "        TY" );
			DisplayCurve( animCurve );
		}
		animCurve = i_node->LclTranslation.GetCurve( i_animLayer, FBXSDK_CURVENODE_COMPONENT_Z );
		if( animCurve )
		{
			FBXSDK_printf( "        TZ\n" );
			DisplayCommon::DisplayString( "        TZ" );
			DisplayCurve( animCurve );
		}

		animCurve = i_node->LclRotation.GetCurve( i_animLayer, FBXSDK_CURVENODE_COMPONENT_X );
		if( animCurve )
		{
			FBXSDK_printf( "        RX\n" );
			DisplayCommon::DisplayString( "        RX" );
			DisplayCurve( animCurve );
		}
		animCurve = i_node->LclRotation.GetCurve( i_animLayer, FBXSDK_CURVENODE_COMPONENT_Y );
		if( animCurve )
		{
			FBXSDK_printf( "        RY\n" );
			DisplayCommon::DisplayString( "        RY" );
			DisplayCurve( animCurve );
		}
		animCurve = i_node->LclRotation.GetCurve( i_animLayer, FBXSDK_CURVENODE_COMPONENT_Z );
		if( animCurve )
		{
			FBXSDK_printf( "        RZ\n" );
			DisplayCommon::DisplayString( "        RZ" );
			DisplayCurve( animCurve );
		}

		animCurve = i_node->LclScaling.GetCurve( i_animLayer, FBXSDK_CURVENODE_COMPONENT_X );
		if( animCurve )
		{
			FBXSDK_printf( "        SX\n" );
			DisplayCommon::DisplayString( "        SX" );
			DisplayCurve( animCurve );
		}
		animCurve = i_node->LclScaling.GetCurve( i_animLayer, FBXSDK_CURVENODE_COMPONENT_Y );
		if( animCurve )
		{
			FBXSDK_printf( "        SY\n" );
			DisplayCommon::DisplayString( "        SY" );
			DisplayCurve( animCurve );
		}
		animCurve = i_node->LclScaling.GetCurve( i_animLayer, FBXSDK_CURVENODE_COMPONENT_Z );
		if( animCurve )
		{
			FBXSDK_printf( "        SZ\n" );
			DisplayCommon::DisplayString( "        SZ" );
			DisplayCurve( animCurve );
		}
	}

	// Display curves specific to a light or marker.
	FbxNodeAttribute *nodeAttribute = i_node->GetNodeAttribute();

	if( nodeAttribute )
	{
		animCurve = nodeAttribute->Color.GetCurve( i_animLayer, FBXSDK_CURVENODE_COLOR_RED );
		if( animCurve )
		{
			FBXSDK_printf( "        Red\n" );
			DisplayCommon::DisplayString( "        Red" );
			DisplayCurve( animCurve );
		}
		animCurve = nodeAttribute->Color.GetCurve( i_animLayer, FBXSDK_CURVENODE_COLOR_GREEN );
		if( animCurve )
		{
			FBXSDK_printf( "        Green\n" );
			DisplayCommon::DisplayString( "        Green" );
			DisplayCurve( animCurve );
		}
		animCurve = nodeAttribute->Color.GetCurve( i_animLayer, FBXSDK_CURVENODE_COLOR_BLUE );
		if( animCurve )
		{
			FBXSDK_printf( "        Blue\n" );
			DisplayCommon::DisplayString( "        Blue" );
			DisplayCurve( animCurve );
		}

		// Display curves specific to a light.
		FbxLight *light = i_node->GetLight();
		if( light )
		{
			animCurve = light->Intensity.GetCurve( i_animLayer );
			if( animCurve )
			{
				FBXSDK_printf( "        Intensity\n" );
				DisplayCommon::DisplayString( "        Intensity" );
				DisplayCurve( animCurve );
			}

			animCurve = light->OuterAngle.GetCurve( i_animLayer );
			if( animCurve )
			{
				FBXSDK_printf( "        Outer Angle\n" );
				DisplayCommon::DisplayString( "        Outer Angle" );
				DisplayCurve( animCurve );
			}

			animCurve = light->Fog.GetCurve( i_animLayer );
			if( animCurve )
			{
				FBXSDK_printf( "        Fog\n" );
				DisplayCommon::DisplayString( "        Fog" );
				DisplayCurve( animCurve );
			}
		}

		// Display curves specific to a camera.
		FbxCamera *camera = i_node->GetCamera();
		if( camera )
		{
			animCurve = camera->FieldOfView.GetCurve( i_animLayer );
			if( animCurve )
			{
				FBXSDK_printf( "        Field of View\n" );
				DisplayCommon::DisplayString( "        Field of View" );
				DisplayCurve( animCurve );
			}

			animCurve = camera->FieldOfViewX.GetCurve( i_animLayer );
			if( animCurve )
			{
				FBXSDK_printf( "        Field of View X\n" );
				DisplayCommon::DisplayString( "        Field of View X" );
				DisplayCurve( animCurve );
			}

			animCurve = camera->FieldOfViewY.GetCurve( i_animLayer );
			if( animCurve )
			{
				FBXSDK_printf( "        Field of View Y\n" );
				DisplayCommon::DisplayString( "        Field of View Y" );
				DisplayCurve( animCurve );
			}

			animCurve = camera->OpticalCenterX.GetCurve( i_animLayer );
			if( animCurve )
			{
				FBXSDK_printf( "        Optical Center X\n" );
				DisplayCommon::DisplayString( "        Optical Center X" );
				DisplayCurve( animCurve );
			}

			animCurve = camera->OpticalCenterY.GetCurve( i_animLayer );
			if( animCurve )
			{
				FBXSDK_printf( "        Optical Center Y\n" );
				DisplayCommon::DisplayString( "        Optical Center Y" );
				DisplayCurve( animCurve );
			}

			animCurve = camera->Roll.GetCurve( i_animLayer );
			if( animCurve )
			{
				FBXSDK_printf( "        Roll\n" );
				DisplayCommon::DisplayString( "        Roll" );
				DisplayCurve( animCurve );
			}
		}

		// Display curves specific to a geometry.
		if (nodeAttribute->GetAttributeType() == FbxNodeAttribute::eMesh ||
			nodeAttribute->GetAttributeType() == FbxNodeAttribute::eNurbs ||
			nodeAttribute->GetAttributeType() == FbxNodeAttribute::ePatch)
		{
			FbxGeometry *geometry = (FbxGeometry*) nodeAttribute;

			int blendShapeDeformerCount = geometry->GetDeformerCount( FbxDeformer::eBlendShape );
			for( int blendShapeIndex = 0; blendShapeIndex<blendShapeDeformerCount; blendShapeIndex++ )
			{
				FbxBlendShape *blendShape = (FbxBlendShape*)geometry->GetDeformer( blendShapeIndex, FbxDeformer::eBlendShape );

				int blendShapeChannelCount = blendShape->GetBlendShapeChannelCount();
				for( int channelIndex = 0; channelIndex<blendShapeChannelCount; channelIndex++ )
				{
					FbxBlendShapeChannel *channel = blendShape->GetBlendShapeChannel( channelIndex );
					const char *channelName = channel->GetName();

					animCurve = geometry->GetShapeChannel( blendShapeIndex, channelIndex, i_animLayer, true );
					if( animCurve )
					{
						FBXSDK_printf( "        Shape %s\n", channelName );
						DisplayCommon::DisplayString( "        Shape ", channelName );
						DisplayCurve( animCurve );
					}
				}
			}
		}
	}

	// Display curves specific to properties
	FbxProperty lProperty = i_node->GetFirstProperty();
	while( lProperty.IsValid() )
	{
		if( lProperty.GetFlag(FbxPropertyAttr::eUserDefined) )
		{
			FbxString lFbxFCurveNodeName  = lProperty.GetName();
			FbxAnimCurveNode* curveNode = lProperty.GetCurveNode( i_animLayer );

			if( !curveNode )
			{
				lProperty = i_node->GetNextProperty( lProperty );
				continue;
			}

			FbxDataType dataType = lProperty.GetPropertyDataType();
			if( dataType.GetType() == eFbxBool || dataType.GetType() == eFbxDouble || dataType.GetType() == eFbxFloat || dataType.GetType() == eFbxInt )
			{
				FbxString message;

				message =  "        Property ";
				message += lProperty.GetName();
				if( lProperty.GetLabel().GetLen() > 0 )
				{
					message += " (Label: ";
					message += lProperty.GetLabel();
					message += ")";
				};

				DisplayCommon::DisplayString( message );

				for( int c = 0; c < curveNode->GetCurveCount(0U); c++ )
				{
					animCurve = curveNode->GetCurve( 0U, c );
					if( animCurve )
						DisplayCurve( animCurve );
				}
			}
			else if( dataType.GetType() == eFbxDouble3 || dataType.GetType() == eFbxDouble4 || dataType.Is(FbxColor3DT) || dataType.Is(FbxColor4DT) )
			{
				char* componentName1 = (dataType.Is(FbxColor3DT) ||dataType.Is(FbxColor4DT)) ? (char*)FBXSDK_CURVENODE_COLOR_RED : (char*)"X";
				char* componentName2 = (dataType.Is(FbxColor3DT) ||dataType.Is(FbxColor4DT)) ? (char*)FBXSDK_CURVENODE_COLOR_GREEN : (char*)"Y";
				char* componentName3 = (dataType.Is(FbxColor3DT) ||dataType.Is(FbxColor4DT)) ? (char*)FBXSDK_CURVENODE_COLOR_BLUE  : (char*)"Z";
				FbxString message;

				message =  "        Property ";
				message += lProperty.GetName();
				if( lProperty.GetLabel().GetLen() > 0 )
				{
					message += " (Label: ";
					message += lProperty.GetLabel();
					message += ")";
				}
				DisplayCommon::DisplayString( message );

				for( int c = 0; c < curveNode->GetCurveCount(0U); c++ )
				{
					animCurve = curveNode->GetCurve( 0U, c );
					if( animCurve )
					{
						DisplayCommon::DisplayString( "        Component ", componentName1 );
						DisplayCurve( animCurve );
					}
				}

				for( int c = 0; c < curveNode->GetCurveCount(1U); c++ )
				{
					animCurve = curveNode->GetCurve(1U, c);
					if( animCurve )
					{
						DisplayCommon::DisplayString( "        Component ", componentName2 );
						DisplayCurve( animCurve );
					}
				}

				for( int c = 0; c < curveNode->GetCurveCount(2U); c++ )
				{
					animCurve = curveNode->GetCurve( 2U, c );
					if( animCurve )
					{
						DisplayCommon::DisplayString( "        Component ", componentName3 );
						DisplayCurve( animCurve );
					}
				}
			}
			else if( dataType.GetType() == eFbxEnum )
			{
				FbxString message;

				message =  "        Property ";
				message += lProperty.GetName();
				if( lProperty.GetLabel().GetLen() > 0 )
				{
					message += " (Label: ";
					message += lProperty.GetLabel();
					message += ")";
				};
				DisplayCommon::DisplayString( message );

				for( int c = 0; c < curveNode->GetCurveCount(0U); c++ )
				{
					animCurve = curveNode->GetCurve( 0U, c );
					if( animCurve )
						DisplayListCurve( animCurve, &lProperty );
				}
			}
		}

		lProperty = i_node->GetNextProperty( lProperty );
	} // while
}
Esempio n. 3
0
void FbxToHkxConverter::extractKeyFramesAndAnnotations(hkxScene *scene, FbxNode* fbxChildNode, hkxNode* newChildNode, int animStackIndex)
{
	FbxAMatrix bindPoseMatrix;
	FbxAnimStack* lAnimStack = NULL;
	int numAnimLayers = 0;
	FbxTimeSpan animTimeSpan;
	
	if (animStackIndex >= 0)
	{
		lAnimStack = m_curFbxScene->GetSrcObject<FbxAnimStack>(animStackIndex);
		numAnimLayers = lAnimStack->GetMemberCount<FbxAnimLayer>();
		animTimeSpan = lAnimStack->GetLocalTimeSpan();
	}

	// Find the time offset (in the "time space" of the FBX file) of the first animation frame
	FbxTime timePerFrame; timePerFrame.SetTime(0, 0, 0, 1, 0, m_curFbxScene->GetGlobalSettings().GetTimeMode());
	const FbxTime startTime = animTimeSpan.GetStart();
	const FbxTime endTime = animTimeSpan.GetStop();

	const hkReal startTimeSeconds = static_cast<hkReal>(startTime.GetSecondDouble());
	const hkReal endTimeSeconds = static_cast<hkReal>(endTime.GetSecondDouble());

	int numFrames = 0;
	bool staticNode = true;

	if (scene->m_sceneLength == 0)
	{
		bindPoseMatrix = fbxChildNode->EvaluateLocalTransform(startTime);
	}
	else
	{
		hkArray<hkStringOld> annotationStrings;
		hkArray<hkReal> annotationTimes;

		HK_ASSERT(0x0, newChildNode->m_keyFrames.getSize() == 0);

		// Sample each animation frame
		for (FbxTime time = startTime, priorSampleTime = endTime;
			 time < endTime;
			 priorSampleTime = time, time += timePerFrame, ++numFrames)
		{
			FbxAMatrix frameMatrix = fbxChildNode->EvaluateLocalTransform(time);
			staticNode = staticNode && (frameMatrix == bindPoseMatrix);

			hkMatrix4 mat;

			// Extract this frame's transform
			convertFbxXMatrixToMatrix4(frameMatrix, mat);
			newChildNode->m_keyFrames.pushBack(mat);

			// Extract all annotation strings for this frame using the deprecated
			// pipeline (new annotations are extracted when sampling attributes)
			if (m_options.m_exportAnnotations && numAnimLayers > 0)
			{
				FbxProperty prop = fbxChildNode->GetFirstProperty();
				while(prop.IsValid())
				{
					FbxString propName  = prop.GetName();
					FbxDataType lDataType = prop.GetPropertyDataType();
					hkStringOld name(propName.Buffer(), (int) propName.GetLen());
					if (name.asUpperCase().beginsWith("HK") && lDataType.GetType() == eFbxEnum)
					{
						FbxAnimLayer* lAnimLayer = lAnimStack->GetMember<FbxAnimLayer>(0);
						FbxAnimCurve* lAnimCurve = prop.GetCurve(lAnimLayer);

						int currentKeyIndex;
						const int keyIndex = (int) lAnimCurve->KeyFind(time, &currentKeyIndex);
						const int priorKeyIndex = (int) lAnimCurve->KeyFind(priorSampleTime);

						// Only store annotations on frames where they're explicitly keyframed, or if this is the first keyframe 
						if (priorKeyIndex != keyIndex)
						{
							const int currentEnumValueIndex = keyIndex < 0 ? (int) lAnimCurve->Evaluate(priorSampleTime) : (int) lAnimCurve->Evaluate(time);
							HK_ASSERT(0x0, currentEnumValueIndex < prop.GetEnumCount());
							const char* enumValue = prop.GetEnumValue(currentEnumValueIndex);
							hkxNode::AnnotationData& annotation = newChildNode->m_annotations.expandOne();
							annotation.m_time = (hkReal) (time - startTime).GetSecondDouble();
							annotation.m_description = (name + hkStringOld(enumValue, hkString::strLen(enumValue))).cString();
						}
					}
					prop = fbxChildNode->GetNextProperty(prop);
				}
			}
		}
	}

	// Replace animation key data for static nodes with just 1 or 2 frames of bind pose data
	if (staticNode)
	{
		// Static nodes in animated scene data are exported with two keys
		const bool exportTwoFramesForStaticNodes = (numFrames > 1);

		// replace transform
		newChildNode->m_keyFrames.setSize(exportTwoFramesForStaticNodes ? 2: 1);
		newChildNode->m_keyFrames.optimizeCapacity(0, true);

		// convert the bind pose transform to Havok format
		convertFbxXMatrixToMatrix4(bindPoseMatrix, newChildNode->m_keyFrames[0]);

		if (exportTwoFramesForStaticNodes)
		{
			newChildNode->m_keyFrames[1] = newChildNode->m_keyFrames[0];
		}
	}

	// Extract all times of actual keyframes for the current node... this can be used by Vision
	if ( m_options.m_storeKeyframeSamplePoints &&
		 newChildNode->m_keyFrames.getSize() > 2 &&
		 numAnimLayers > 0 )
	{
		FbxAnimLayer* lAnimLayer = lAnimStack->GetMember<FbxAnimLayer>(0);

		extractKeyTimes(fbxChildNode, lAnimLayer, FBXSDK_CURVENODE_TRANSLATION, newChildNode, startTimeSeconds, endTimeSeconds);
		extractKeyTimes(fbxChildNode, lAnimLayer, FBXSDK_CURVENODE_ROTATION, newChildNode, startTimeSeconds, endTimeSeconds);
		extractKeyTimes(fbxChildNode, lAnimLayer, FBXSDK_CURVENODE_SCALING, newChildNode, startTimeSeconds, endTimeSeconds);
		extractKeyTimes(fbxChildNode, lAnimLayer, FBXSDK_CURVENODE_COMPONENT_X, newChildNode, startTimeSeconds, endTimeSeconds);
		extractKeyTimes(fbxChildNode, lAnimLayer, FBXSDK_CURVENODE_COMPONENT_Y, newChildNode, startTimeSeconds, endTimeSeconds);
		extractKeyTimes(fbxChildNode, lAnimLayer, FBXSDK_CURVENODE_COMPONENT_Z, newChildNode, startTimeSeconds, endTimeSeconds);

		if (newChildNode->m_linearKeyFrameHints.getSize() > 1)
		{
			hkSort(newChildNode->m_linearKeyFrameHints.begin(), newChildNode->m_linearKeyFrameHints.getSize());
		}
	}
}