コード例 #1
0
void hkDemoDatabase::rebuildDatabase()
{
	m_demos.clear();

	//
	// Normalize and collect all demo register entries
	// into a temporary array
	//
	hkArray<hkDemoEntry*> demos;	
	hkDemoEntryRegister* e = s_demoList;
	while(e)
	{
		// Convert the file path to Havok path format
		hkArray<char> buffer;
		const char* tmp = hkNativeFileSystem::platformToHavokConvertPath( e->m_demoPath, buffer );
		hkString resourcePath( hkDemoFileSystem::removeDemoBasePath( tmp, buffer ) );

		int lastSlash  = resourcePath.lastIndexOf('/');		
		HK_ASSERT2(0x6e7879d4, lastSlash >= 0,  "probably a metrowerks build with no 'pragma fullpath_file on': " << resourcePath );

		// Copy as the menu path
		hkString menuPath( resourcePath.substr(0, lastSlash) );	// remove the demo filename for the menu

		// If we have a variant, append the variant name
		if( e->m_variantName )
		{
			menuPath += "/";
			menuPath += e->m_variantName;
		}

#ifdef USING_DEMO_FILTERS
		{
			hkString name(menuPath);
			bool valid = false;
			for (int f=0; f < HK_COUNT_OF(demoFilters); f++)
			{
				valid |= name.beginsWith(demoFilters[f]);
			}
			if (!valid)
			{
				e = e->m_next;
				continue;
			}
		}
#endif

		// Store the entry
		hkDemoEntry* entry = new hkDemoEntry();
		entry->m_func = e->m_func;
		entry->m_demoTypeFlags = e->m_demoTypeFlags;
		entry->m_menuPath = menuPath;
		entry->m_demoPath = resourcePath;
		entry->m_variantId = e->m_variantId;
		entry->m_help = e->m_help;
		entry->m_details = e->m_details;

		if ( e->m_createEntryFunc )	// now we have a create other demos function
		{
			e->m_createEntryFunc(*entry, demos);
			delete entry;
		}
		else
		{
			demos.pushBack(entry);
		}
		e = e->m_next;
	}

	HK_ASSERT2(0x4467bbc3, demos.getSize() != 0, "No demos registered!");

	// find a common root for the demos, if any
	m_prefix = findCommonRootPath( demos );

	// strip the common root plus from the names
	int prefixLen = m_prefix.getLength();
	for(int i = 0; i < demos.getSize(); ++i)
	{
		// prune the prefix from each name 
		hkString& n = demos[i]->m_menuPath;
		if( n[0] == '*' ) // this comes from unit tests, */means "put me at the demos level"???
		{
			n.setAsSubstr(2);
		}
		else if( m_prefix.getLength() > 0 )
		{
			n.setAsSubstr( prefixLen, n.getLength() - prefixLen );
		}
	}

	//
	// Sort the array alphabetically and by ID in the same variant group
	//
	hkSort( demos.begin(), demos.getSize(), demoEntryPathAndVariantIdLess() );

	// Collect the menu order files into an array
	extern const char* DemoOrder[];
	// Build the member demos, sorting according to the menu order
	for (int i = 0; DemoOrder[i] != 0; i++)
	{
		// the demos are already sorted alphabetically
		int j=0;
		// look for the first matching path.. 
		while( j < demos.getSize() && !( demos[j]!=HK_NULL && demos[j]->m_menuPath.beginsWith(DemoOrder[i]) ) ) 
			++j;
		// ..and add it together with all the following matching ones
		while( j < demos.getSize() && demos[j]!=HK_NULL && (demos[j]->m_menuPath.beginsWith(DemoOrder[i])) ) 
		{
			m_demos.pushBack( *(demos[j]) );
			delete demos[j];
			demos[j] = HK_NULL;
			++j;
		}
	}

	// Store any leftover demos
	for (int j = 0; j < demos.getSize(); j++)
	{
		if(demos[j] != HK_NULL)
		{
			m_demos.pushBack( *(demos[j]) );
		}
		delete demos[j];
	}
	// cleanup
	demos.clear();

	/*
	//
	// Write the demo list to a file
	//
	hkOstream stream(HK_DEMO_LIST_FILENAME);
	if ( stream.isOk() )
	{
	stream << ";Havok '" << productCode << "' demo list:" << hkendl << hkendl;
	for (int j = 0; j < m_demos.getSize(); j++)
	{
	stream << m_demos[j].m_menuPath << hkendl;
	}
	}
	*/
}
コード例 #2
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());
		}
	}
}