Exemplo n.º 1
0
bool FArchiveXML::LoadTransformSkew(FCDObject* object, xmlNode* skewNode)
{
	FCDTSkew* tSkew = (FCDTSkew*)object;

	const char* content = FUDaeParser::ReadNodeContentDirect(skewNode);
	FloatList factors;
	factors.reserve(7);
	FUStringConversion::ToFloatList(content, factors);
	if (factors.size() != 7) return false;

	tSkew->SetAngle(factors[0]);
	tSkew->SetRotateAxis(FMVector3(factors[1], factors[2], factors[3]));
	tSkew->SetAroundAxis(FMVector3(factors[4], factors[5], factors[6]));

	// Check and pre-process the axises
	if (IsEquivalent(tSkew->GetRotateAxis(), FMVector3::Origin) || IsEquivalent(tSkew->GetAroundAxis(), FMVector3::Origin)) return false;
	tSkew->SetRotateAxis(tSkew->GetRotateAxis().Normalize());
	tSkew->SetAroundAxis(tSkew->GetAroundAxis().Normalize());

	// Register the animated values
	FArchiveXML::LoadAnimatable(&tSkew->GetSkew(), skewNode);

	tSkew->SetDirtyFlag();
	return true;
}
Exemplo n.º 2
0
void FloatPlacement::initFloatTypeCO(FloatList const & floats)
{
	if (float_list_ == &floats)
		return;

	float_list_ = &floats;
	floatTypeCO->clear();
	FloatList::const_iterator it = floats.begin();
	FloatList::const_iterator const end = floats.end();
	for (; it != end; ++it) {
		floatTypeCO->addItem(qt_(it->second.name()),
				     toqstr(it->second.floattype()));
	}
}
Exemplo n.º 3
0
bool FArchiveXML::LoadTransformTranslation(FCDObject* object, xmlNode* node)
{
	FCDTTranslation* tTranslation = (FCDTTranslation*)object;

	const char* content = FUDaeParser::ReadNodeContentDirect(node);
	FloatList factors;
	factors.reserve(3);
	FUStringConversion::ToFloatList(content, factors);
	if (factors.size() != 3) return false;
	
	tTranslation->SetTranslation(factors[0], factors[1], factors[2]);
	FArchiveXML::LoadAnimatable(&tTranslation->GetTranslation(), node);
	
	tTranslation->SetDirtyFlag();
	return true;
}	
Exemplo n.º 4
0
bool FArchiveXML::LoadTransformScale(FCDObject* object, xmlNode* node)
{ 
	FCDTScale* tScale = (FCDTScale*)object;

	const char* content = FUDaeParser::ReadNodeContentDirect(node);
	FloatList factors;
	factors.reserve(3);
	FUStringConversion::ToFloatList(content, factors);
	if (factors.size() != 3) return false;

	tScale->SetScale(factors[0], factors[1], factors[2]);

	// Register the animated values
	FArchiveXML::LoadAnimatable(&tScale->GetScale(), node);

	tScale->SetDirtyFlag();
	return true;
}
Exemplo n.º 5
0
bool FArchiveXML::LoadTransformLookAt(FCDObject* object, xmlNode* lookAtNode)
{ 
	FCDTLookAt* tLookAt = (FCDTLookAt*)object;

	const char* content = FUDaeParser::ReadNodeContentDirect(lookAtNode);
	FloatList factors;
	factors.reserve(9);
	FUStringConversion::ToFloatList(content, factors);
	if (factors.size() != 9) return false;

	tLookAt->GetPosition().Set(factors[0], factors[1], factors[2]);
	tLookAt->GetTarget().Set(factors[3], factors[4], factors[5]);
	tLookAt->GetUp().Set(factors[6], factors[7], factors[8]);

	// Register the animated values
	FArchiveXML::LoadAnimatable(&tLookAt->GetLookAt(), lookAtNode);

	tLookAt->SetDirtyFlag();
	return true;
}
Exemplo n.º 6
0
 float *flattenFVecList(int t, int vecDim, FloatVecList* pfloatVecList)
 {
   if (NULL == pfloatVecList)
     return false;
     int szvec = 0;
     int arraySz = 0;
     float *array = NULL;
     // walk through the vector list and check few things then send the packed version
     float *p = NULL;
     for(int i=0; i<(int)pfloatVecList->size(); i++)
     {
         if(szvec == 0) {
             szvec = (int)((*pfloatVecList)[i]->size());
             arraySz = szvec * pfloatVecList->size();
             p = array = new float[arraySz]; // we assume all vectors are the same size
         }
         else if(szvec != (*pfloatVecList)[i]->size()) {
             yyerror("Vector list has inconsistent vectors\n");
             continue;
         }
         FloatList* pfl = (*pfloatVecList)[i];
         if (NULL!=pfl)
         {
         for(int j=0; j<(int)pfl->size(); j++)
             *p++ = (*pfl)[j];
         delete pfl;
           pfl = NULL;
         }
     }
     if(vecDim < 0)
         vecDim = (int)pfloatVecList->size();
     // we do the test here in any case : the previous loop needed to do some "delete" anyways
     if((t * vecDim) != (arraySz))
     {
         yyerror("Vector dimension in value assignment don't match the type\n");
         delete array;
         return NULL;
     }
     return array;
 }
Exemplo n.º 7
0
	// Retrieves a list of floats from a source node
	// Returns the data's stride.
	uint32 ReadSource(xmlNode* sourceNode, FloatList& array)
	{
		uint32 stride = 0;
		if (sourceNode != NULL)
		{
			// Get the accessor's count
			xmlNode* accessorNode = FindTechniqueAccessor(sourceNode);
			stride = ReadNodeStride(accessorNode);
			array.resize(ReadNodeCount(accessorNode) * stride);

			xmlNode* arrayNode = FindChildByType(sourceNode, DAE_FLOAT_ARRAY_ELEMENT);
			const char* arrayContent = ReadNodeContentDirect(arrayNode);
			FUStringConversion::ToFloatList(arrayContent, array);
		}
		return stride;
	}
Exemplo n.º 8
0
	void GenerateSampledAnimation(FCDSceneNode* node)
	{
		sampleKeys.clear();
		sampleValues.clear();

		FCDAnimatedList animateds;
		// Special case for rotation angles: need to check for changes that are greater than 180 degrees.
		Int32List angleIndices;
		
		// Collect all the animation curves
		size_t transformCount = node->GetTransformCount();
		for (size_t t = 0; t < transformCount; ++t)
		{
			FCDTransform* transform = node->GetTransform(t);
			FCDAnimated* animated = transform->GetAnimated();
			if (animated != NULL)
			{
				if (animated->HasCurve()) animateds.push_back(animated);

				// Figure out whether this is a rotation and then, which animated value contains the angle.
				if (!transform->HasType(FCDTRotation::GetClassType())) angleIndices.push_back(-1);
				else angleIndices.push_back((int32) animated->FindQualifier(".ANGLE"));
			}
		}
		if (animateds.empty()) return;

		// Make a list of the ordered key times to sample
		size_t animatedsCount = animateds.size();
		for (size_t i = 0; i < animatedsCount; ++i)
		{
			FCDAnimated* animated = animateds[i];
			int32 angleIndex = angleIndices[i];

			const FCDAnimationCurveListList& allCurves = animated->GetCurves();
			size_t valueCount = allCurves.size();
			for (size_t curveIndex = 0; curveIndex < valueCount; ++curveIndex)
			{
				const FCDAnimationCurveTrackList& curves = allCurves[curveIndex];
				if (curves.empty()) continue;

				size_t curveKeyCount = curves.front()->GetKeyCount();
				const FCDAnimationKey** curveKeys = curves.front()->GetKeys();
				size_t sampleKeyCount = sampleKeys.size();
				
				// Merge this curve's keys in with the sample keys
				// This assumes both key lists are in increasing order
				size_t s = 0, c = 0;
				while (s < sampleKeyCount && c < curveKeyCount)
				{
					float sampleKey = sampleKeys[s], curveKey = curveKeys[c]->input;
					if (IsEquivalent(sampleKey, curveKey)) { ++s; ++c; }
					else if (sampleKey < curveKey) { ++s; }
					else
					{
						// Add this curve key to the sampling key list
						sampleKeys.insert(sampleKeys.begin() + (s++), curveKeys[c++]->input);
						sampleKeyCount++;
					}
				}

				// Add all the left-over curve keys to the sampling key list
				while (c < curveKeyCount) sampleKeys.push_back(curveKeys[c++]->input);

				// Check for large angular rotations..
				if (angleIndex == (intptr_t) curveIndex)
				{
					for (size_t c = 1; c < curveKeyCount; ++c)
					{
						const FCDAnimationKey* previousKey = curveKeys[c - 1];
						const FCDAnimationKey* currentKey = curveKeys[c];
						float halfWrapAmount = (currentKey->output - previousKey->output) / 180.0f;
						halfWrapAmount *= FMath::Sign(halfWrapAmount);
						if (halfWrapAmount >= 1.0f)
						{
							// Need to add sample times.
							size_t addSampleCount = (size_t) floorf(halfWrapAmount);
							for (size_t d = 1; d <= addSampleCount; ++d)
							{
								float fd = (float) d;
								float fid = (float) (addSampleCount + 1 - d);
								float addSampleTime = (currentKey->input * fd + previousKey->input * fid) / (fd + fid);
								
								// Sorted insert.
								float* endIt = sampleKeys.end();
								for (float* sampleKeyTime = sampleKeys.begin(); sampleKeyTime != endIt; ++sampleKeyTime)
								{
									if (IsEquivalent(*sampleKeyTime, addSampleTime)) break;
									else if (*sampleKeyTime > addSampleTime)
									{
										sampleKeys.insert(sampleKeyTime, addSampleTime);
										break;
									}
								}
							}
						}
					}
				}
			}
		}
		size_t sampleKeyCount = sampleKeys.size();
		if (sampleKeyCount == 0) return;

		// Pre-allocate the value array;
		sampleValues.reserve(sampleKeyCount);
		
		// Sample the scene node transform
		for (size_t i = 0; i < sampleKeyCount; ++i)
		{
			float sampleTime = sampleKeys[i];
			for (FCDAnimatedList::iterator it = animateds.begin(); it != animateds.end(); ++it)
			{
				// Sample each animated, which changes the transform values directly
				(*it)->Evaluate(sampleTime);
			}

			// Retrieve the new transform matrix for the COLLADA scene node
			sampleValues.push_back(node->ToMatrix());
		}
	}
Exemplo n.º 9
0
	void ClearSampledAnimation()
	{
		sampleKeys.clear();
		sampleValues.clear();
	}
Exemplo n.º 10
0
bool FArchiveXML::LoadAnimationChannel(FCDObject* object, xmlNode* channelNode)
{ 
	FCDAnimationChannel* animationChannel = (FCDAnimationChannel*)object;
	FCDAnimationChannelData& data = FArchiveXML::documentLinkDataMap[animationChannel->GetDocument()].animationChannelData[animationChannel];

	bool status = true;

	// Read the channel-specific ID
	fm::string daeId = ReadNodeId(channelNode);
	fm::string samplerId = ReadNodeSource(channelNode);
	ReadNodeTargetProperty(channelNode, data.targetPointer, data.targetQualifier);

#ifdef DONT_DEFINE_THIS
	FCDAnimation* anim = animationChannel->GetParent();
	FCDExtra* extra = anim->GetExtra();
	extra->SetTransientFlag(); // Dont save this, its wasted whatever it is.
	FCDEType* type = extra->AddType("AnimTargets");
	FCDETechnique* teq = type->AddTechnique("TEMP");
	teq->AddChildNode("pointer")->SetContent(TO_FSTRING(data.targetPointer));
	teq->AddChildNode("pointer")->SetContent(TO_FSTRING(data.targetQualifier));
#endif
	


	xmlNode* samplerNode = FArchiveXML::FindChildByIdFCDAnimation(animationChannel->GetParent(), samplerId);
	if (samplerNode == NULL || !IsEquivalent(samplerNode->name, DAE_SAMPLER_ELEMENT))
	{
		FUError::Error(FUError::ERROR_LEVEL, FUError::ERROR_MISSING_ELEMENT, channelNode->line);
		return false;
	}

	// Find and process the sources
	xmlNode* inputSource = NULL, * outputSource = NULL, * inTangentSource = NULL, * outTangentSource = NULL, * tcbSource = NULL, * easeSource = NULL, * interpolationSource = NULL;
	xmlNodeList samplerInputNodes;
	fm::string inputDriver;
	FindChildrenByType(samplerNode, DAE_INPUT_ELEMENT, samplerInputNodes);
	for (size_t i = 0; i < samplerInputNodes.size(); ++i) // Don't use iterator here because we are possibly appending source nodes in the loop
	{
		xmlNode* inputNode = samplerInputNodes[i];
		fm::string sourceId = ReadNodeSource(inputNode);
		xmlNode* sourceNode = FArchiveXML::FindChildByIdFCDAnimation(animationChannel->GetParent(), sourceId);
		fm::string sourceSemantic = ReadNodeSemantic(inputNode);

		if (sourceSemantic == DAE_INPUT_ANIMATION_INPUT) inputSource = sourceNode;
		else if (sourceSemantic == DAE_OUTPUT_ANIMATION_INPUT) outputSource = sourceNode;
		else if (sourceSemantic == DAE_INTANGENT_ANIMATION_INPUT) inTangentSource = sourceNode;
		else if (sourceSemantic == DAE_OUTTANGENT_ANIMATION_INPUT) outTangentSource = sourceNode;
		else if (sourceSemantic == DAEFC_TCB_ANIMATION_INPUT) tcbSource = sourceNode;
		else if (sourceSemantic == DAEFC_EASE_INOUT_ANIMATION_INPUT) easeSource = sourceNode;
		else if (sourceSemantic == DAE_INTERPOLATION_ANIMATION_INPUT) interpolationSource = sourceNode;
		else if (sourceSemantic == DAEMAYA_DRIVER_INPUT) inputDriver = sourceId;
	}
	if (inputSource == NULL || outputSource == NULL)
	{
		FUError::Error(FUError::ERROR_LEVEL, FUError::ERROR_MISSING_INPUT, samplerNode->line);
		return false;
	}

	// Calculate the number of curves that in contained by this channel
	xmlNode* outputAccessor = FindTechniqueAccessor(outputSource);
	fm::string accessorStrideString = ReadNodeProperty(outputAccessor, DAE_STRIDE_ATTRIBUTE);
	uint32 curveCount = FUStringConversion::ToUInt32(accessorStrideString);
	if (curveCount == 0) curveCount = 1;

	// Create the animation curves
	for (uint32 i = 0; i < curveCount; ++i)
	{
		animationChannel->AddCurve();
	}

	// Read in the animation curves
	// The input keys and interpolations are shared by all the curves
	FloatList inputs;
    ReadSource(inputSource, inputs);
	size_t keyCount = inputs.size();
	if (keyCount == 0) return true; // Valid although very boring channel.

	UInt32List interpolations; interpolations.reserve(keyCount);
	ReadSourceInterpolation(interpolationSource, interpolations);
	if (interpolations.size() < keyCount)
	{
		// Not enough interpolation types provided, so append BEZIER as many times as needed.
		interpolations.insert(interpolations.end(), keyCount - interpolations.size(), FUDaeInterpolation::FromString(""));
	}

	// Read in the interleaved outputs as floats
	fm::vector<FloatList> tempFloatArrays;
	tempFloatArrays.resize(curveCount);
	fm::pvector<FloatList> outArrays(curveCount);
	for (uint32 i = 0; i < curveCount; ++i) outArrays[i] = &tempFloatArrays[i];
	ReadSourceInterleaved(outputSource, outArrays);
	for (uint32 i = 0; i < curveCount; ++i)
	{
		// Fill in the output array with zeroes, if it was not large enough.
		if (tempFloatArrays[i].size() < keyCount)
		{
			tempFloatArrays[i].insert(tempFloatArrays[i].end(), keyCount - tempFloatArrays[i].size(), 0.0f);
		}

		// Create all the keys, on the curves, according to the interpolation types.
		for (size_t j = 0; j < keyCount; ++j)
		{
			FCDAnimationKey* key = animationChannel->GetCurve(i)->AddKey((FUDaeInterpolation::Interpolation) interpolations[j]);
			key->input = inputs[j];
			key->output = tempFloatArrays[i][j];

			// Set the default values for Bezier/TCB interpolations.
			if (key->interpolation == FUDaeInterpolation::BEZIER)
			{
				FCDAnimationKeyBezier* bkey = (FCDAnimationKeyBezier*) key;
				float previousInput = (j == 0) ? inputs[j] - 1.0f : inputs[j-1];
				float nextInput = (j == keyCount - 1) ? inputs[j] + 1.0f : inputs[j+1];
				bkey->inTangent.x = (previousInput + 2.0f * bkey->input) / 3.0f;
				bkey->outTangent.x = (nextInput + 2.0f * bkey->input) / 3.0f;
				bkey->inTangent.y = bkey->outTangent.y = bkey->output;
			}
			else if (key->interpolation == FUDaeInterpolation::TCB)
			{
				FCDAnimationKeyTCB* tkey = (FCDAnimationKeyTCB*) key;
				tkey->tension = tkey->continuity = tkey->bias = 0.5f;
				tkey->easeIn = tkey->easeOut = 0.0f;
			}
		}
	}
	tempFloatArrays.clear();

	// Read in the interleaved in_tangent source.
	if (inTangentSource != NULL)
	{
		fm::vector<FMVector2List> tempVector2Arrays;
		tempVector2Arrays.resize(curveCount);
		fm::pvector<FMVector2List> arrays(curveCount);
		for (uint32 i = 0; i < curveCount; ++i) arrays[i] = &tempVector2Arrays[i];

		uint32 stride = ReadSourceInterleaved(inTangentSource, arrays);
		if (stride == curveCount)
		{
			// Backward compatibility with 1D tangents.
			// Remove the relativity from the 1D tangents and calculate the second-dimension.
			for (uint32 i = 0; i < curveCount; ++i)
			{
				FMVector2List& inTangents = tempVector2Arrays[i];
				FCDAnimationKey** keys = animationChannel->GetCurve(i)->GetKeys();
				size_t end = min(inTangents.size(), keyCount);
				for (size_t j = 0; j < end; ++j)
				{
					if (keys[j]->interpolation == FUDaeInterpolation::BEZIER)
					{
						FCDAnimationKeyBezier* bkey = (FCDAnimationKeyBezier*) keys[j];
						bkey->inTangent.y = bkey->output - inTangents[j].x;
					}
				}
			}
		}
		else if (stride == curveCount * 2)
		{
			// This is the typical, 2D tangent case.
			for (uint32 i = 0; i < curveCount; ++i)
			{
				FMVector2List& inTangents = tempVector2Arrays[i];
				FCDAnimationKey** keys = animationChannel->GetCurve(i)->GetKeys();
				size_t end = min(inTangents.size(), keyCount);
				for (size_t j = 0; j < end; ++j)
				{
					if (keys[j]->interpolation == FUDaeInterpolation::BEZIER)
					{
						FCDAnimationKeyBezier* bkey = (FCDAnimationKeyBezier*) keys[j];
						bkey->inTangent = inTangents[j];
					}
				}
			}
		}
	}

	// Read in the interleaved out_tangent source.
	if (outTangentSource != NULL)
	{
		fm::vector<FMVector2List> tempVector2Arrays;
		tempVector2Arrays.resize(curveCount);
		fm::pvector<FMVector2List> arrays(curveCount);
		for (uint32 i = 0; i < curveCount; ++i) arrays[i] = &tempVector2Arrays[i];

		uint32 stride = ReadSourceInterleaved(outTangentSource, arrays);
		if (stride == curveCount)
		{
			// Backward compatibility with 1D tangents.
			// Remove the relativity from the 1D tangents and calculate the second-dimension.
			for (uint32 i = 0; i < curveCount; ++i)
			{
				FMVector2List& outTangents = tempVector2Arrays[i];
				FCDAnimationKey** keys = animationChannel->GetCurve(i)->GetKeys();
				size_t end = min(outTangents.size(), keyCount);
				for (size_t j = 0; j < end; ++j)
				{
					if (keys[j]->interpolation == FUDaeInterpolation::BEZIER)
					{
						FCDAnimationKeyBezier* bkey = (FCDAnimationKeyBezier*) keys[j];
						bkey->outTangent.y = bkey->output + outTangents[j].x;
					}
				}
			}
		}
		else if (stride == curveCount * 2)
		{
			// This is the typical, 2D tangent case.
			for (uint32 i = 0; i < curveCount; ++i)
			{
				FMVector2List& outTangents = tempVector2Arrays[i];
				FCDAnimationKey** keys = animationChannel->GetCurve(i)->GetKeys();
				size_t end = min(outTangents.size(), keyCount);
				for (size_t j = 0; j < end; ++j)
				{
					if (keys[j]->interpolation == FUDaeInterpolation::BEZIER)
					{
						FCDAnimationKeyBezier* bkey = (FCDAnimationKeyBezier*) keys[j];
						bkey->outTangent = outTangents[j];
					}
				}
			}
		}
	}

	if (tcbSource != NULL)
	{
		//Process TCB parameters
		fm::vector<FMVector3List> tempVector3Arrays;
		tempVector3Arrays.resize(curveCount);
		fm::pvector<FMVector3List> arrays(curveCount);
		for (uint32 i = 0; i < curveCount; ++i) arrays[i] = &tempVector3Arrays[i];

		ReadSourceInterleaved(tcbSource, arrays);

		for (uint32 i = 0; i < curveCount; ++i)
		{
			FMVector3List& tcbs = tempVector3Arrays[i];
			FCDAnimationKey** keys = animationChannel->GetCurve(i)->GetKeys();
			size_t end = min(tcbs.size(), keyCount);
			for (size_t j = 0; j < end; ++j)
			{
				if (keys[j]->interpolation == FUDaeInterpolation::TCB)
				{
					FCDAnimationKeyTCB* tkey = (FCDAnimationKeyTCB*) keys[j];
					tkey->tension = tcbs[j].x;
					tkey->continuity = tcbs[j].y;
					tkey->bias = tcbs[j].z;
				}
			}
		}
	}

	if (easeSource != NULL)
	{
		//Process Ease-in and ease-out data
		fm::vector<FMVector2List> tempVector2Arrays;
		tempVector2Arrays.resize(curveCount);
		fm::pvector<FMVector2List> arrays(curveCount);
		for (uint32 i = 0; i < curveCount; ++i) arrays[i] = &tempVector2Arrays[i];

		ReadSourceInterleaved(easeSource, arrays);

		for (uint32 i = 0; i < curveCount; ++i)
		{
			FMVector2List& eases = tempVector2Arrays[i];
			FCDAnimationKey** keys = animationChannel->GetCurve(i)->GetKeys();
			size_t end = min(eases.size(), keyCount);
			for (size_t j = 0; j < end; ++j)
			{
				if (keys[j]->interpolation == FUDaeInterpolation::TCB)
				{
					FCDAnimationKeyTCB* tkey = (FCDAnimationKeyTCB*) keys[j];
					tkey->easeIn = eases[j].x;
					tkey->easeOut = eases[j].y;
				}
			}
		}
	}

	// Read in the pre/post-infinity type
	xmlNodeList mayaParameterNodes; StringList mayaParameterNames;
	xmlNode* mayaTechnique = FindTechnique(inputSource, DAEMAYA_MAYA_PROFILE);
	FindParameters(mayaTechnique, mayaParameterNames, mayaParameterNodes);
	size_t parameterCount = mayaParameterNodes.size();
	for (size_t i = 0; i < parameterCount; ++i)
	{
		xmlNode* parameterNode = mayaParameterNodes[i];
		const fm::string& paramName = mayaParameterNames[i];
		const char* content = ReadNodeContentDirect(parameterNode);

		if (paramName == DAEMAYA_PREINFINITY_PARAMETER)
		{
			size_t curveCount = animationChannel->GetCurveCount();
			for (size_t c = 0; c < curveCount; ++c)
			{
				animationChannel->GetCurve(c)->SetPreInfinity(FUDaeInfinity::FromString(content));
			}
		}
		else if (paramName == DAEMAYA_POSTINFINITY_PARAMETER)
		{
			size_t curveCount = animationChannel->GetCurveCount();
			for (size_t c = 0; c < curveCount; ++c)
			{
				animationChannel->GetCurve(c)->SetPostInfinity(FUDaeInfinity::FromString(content));
			}
		}
		else
		{
			// Look for driven-key input target
			if (paramName == DAE_INPUT_ELEMENT)
			{
				fm::string semantic = ReadNodeSemantic(parameterNode);
				if (semantic == DAEMAYA_DRIVER_INPUT)
				{
					inputDriver = ReadNodeSource(parameterNode);
				}
			}
		}
	}

	if (!inputDriver.empty())
	{
		const char* driverTarget = FUDaeParser::SkipPound(inputDriver);
		if (driverTarget != NULL)
		{
			fm::string driverQualifierValue;
			FUStringConversion::SplitTarget(driverTarget, data.driverPointer, driverQualifierValue);
			data.driverQualifier = FUStringConversion::ParseQualifier(driverQualifierValue);
			if (data.driverQualifier < 0) data.driverQualifier = 0;
		}
	}
	animationChannel->SetDirtyFlag();

	return status;
}
	//---------------------------------------------------------------
	void ControllerExporter::exportMorphController( ExportNode* exportNode, MorphController* morphController, const String& controllerId, const String& morphSource )
	{
		MorphR3* morpher = morphController->getMorph();


		FloatList listOfWeights;
		StringList listOfTargetIds;

		String weightsId = controllerId + WEIGHTS_SOURCE_ID_SUFFIX;

		size_t channelBankCount = morpher->chanBank.size();
		for ( size_t i = 0; i<channelBankCount; ++i)
		{
			morphChannel& channel = morpher->chanBank[i];
			
			if (!channel.mActive || channel.mNumPoints == 0) 
				continue;

			INode* targetINode = channel.mConnection;

			listOfWeights.push_back(ConversionFunctors::fromPercent(channel.cblock->GetFloat(morphChannel::cblock_weight_index, mDocumentExporter->getOptions().getAnimationStart())));

			Control* weightController = channel.cblock->GetController(morphChannel::cblock_weight_index);
			mDocumentExporter->getAnimationExporter()->addAnimatedFloat(weightController, weightsId, EMPTY_STRING, (int)i, true, &ConversionFunctors::fromPercent );

			if ( !targetINode )
			{
				MorphControllerHelperGeometry morphControllerHelperGeometry;
				morphControllerHelperGeometry.exportNode = exportNode;
				morphControllerHelperGeometry.controllerId = controllerId;
				morphControllerHelperGeometry.morphController = morphController;
				morphControllerHelperGeometry.channelBankindex = i;
				
				String targetId = ExportSceneGraph::getMorphControllerHelperId(morphControllerHelperGeometry);
				listOfTargetIds.push_back(targetId);
			}
			else
			{
				ExportNode* targetExportNode = mExportSceneGraph->getExportNode(targetINode);
				assert(targetExportNode);

				ExportNode* geometryExportNode = mDocumentExporter->getExportedObjectExportNode(ObjectIdentifier(targetExportNode->getInitialPose()));
				assert( geometryExportNode );
//				listOfTargetIds.push_back(geometryExportNode);
				listOfTargetIds.push_back(GeometriesExporter::getGeometryId(*geometryExportNode));
			}
		}

		openMorph(controllerId, EMPTY_STRING, morphSource);

		//export weights source
		String targetId = controllerId + TARGETS_SOURCE_ID_SUFFIX;
		COLLADASW::IdRefSource targetsSource(mSW);
		targetsSource.setId(targetId);
		targetsSource.setArrayId(targetId + ARRAY_ID_SUFFIX);
		targetsSource.setAccessorStride(1);
		targetsSource.getParameterNameList().push_back("MORPH_TARGET");
		targetsSource.setAccessorCount((unsigned long)listOfTargetIds.size());
		targetsSource.prepareToAppendValues();

		for ( StringList::const_iterator it = listOfTargetIds.begin(); it != listOfTargetIds.end(); ++it)
			targetsSource.appendValues(*it);

		targetsSource.finish();


		//export weights source
		COLLADASW::FloatSource weightsSource(mSW);
		weightsSource.setId(weightsId);
		weightsSource.setArrayId(weightsId + ARRAY_ID_SUFFIX);
		weightsSource.setAccessorStride(1);
		weightsSource.getParameterNameList().push_back("MORPH_WEIGHT");
		weightsSource.setAccessorCount((unsigned long)listOfWeights.size());
		weightsSource.prepareToAppendValues();
		
		for ( FloatList::const_iterator it = listOfWeights.begin(); it != listOfWeights.end(); ++it)
			weightsSource.appendValues(*it);
		
		weightsSource.finish();


		COLLADASW::TargetsElement targets(mSW);
		targets.getInputList().push_back(COLLADASW::Input(COLLADASW::InputSemantic::MORPH_TARGET, "#" + targetId));
		targets.getInputList().push_back(COLLADASW::Input(COLLADASW::InputSemantic::MORPH_WEIGHT, "#" + weightsId));
		targets.add();

		closeMorph();

	}
Exemplo n.º 12
0
void ReindexGeometry(FCDGeometryPolygons* polys, FCDSkinController* skin)
{
	// Given geometry with:
	//   positions, normals, texcoords, bone blends
	// each with their own data array and index array, change it to
	// have a single optimised index array shared by all vertexes.

	FCDGeometryPolygonsInput* inputPosition = polys->FindInput(FUDaeGeometryInput::POSITION);
	FCDGeometryPolygonsInput* inputNormal   = polys->FindInput(FUDaeGeometryInput::NORMAL);
	FCDGeometryPolygonsInput* inputTexcoord = polys->FindInput(FUDaeGeometryInput::TEXCOORD);

	size_t numVertices = polys->GetFaceVertexCount();

	assert(inputPosition->GetIndexCount() == numVertices);
	assert(inputNormal  ->GetIndexCount() == numVertices);
	assert(inputTexcoord->GetIndexCount() == numVertices);

	const uint32* indicesPosition = inputPosition->GetIndices();
	const uint32* indicesNormal   = inputNormal->GetIndices();
	const uint32* indicesTexcoord = inputTexcoord->GetIndices();

	assert(indicesPosition);
	assert(indicesNormal);
	assert(indicesTexcoord); // TODO - should be optional, because textureless meshes aren't unreasonable

	FCDGeometrySourceList texcoordSources;
	polys->GetParent()->FindSourcesByType(FUDaeGeometryInput::TEXCOORD, texcoordSources);

	FCDGeometrySource* sourcePosition = inputPosition->GetSource();
	FCDGeometrySource* sourceNormal   = inputNormal  ->GetSource();

	const float* dataPosition = sourcePosition->GetData();
	const float* dataNormal   = sourceNormal  ->GetData();

	if (skin)
	{
#ifndef NDEBUG
		size_t numVertexPositions = sourcePosition->GetDataCount() / sourcePosition->GetStride();
		assert(skin->GetInfluenceCount() == numVertexPositions);
#endif
	}

	uint32 stridePosition = sourcePosition->GetStride();
	uint32 strideNormal   = sourceNormal  ->GetStride();

	std::vector<uint32> indicesCombined;
	std::vector<VertexData> vertexes;
	InserterWithoutDuplicates<VertexData> inserter(vertexes);

	for (size_t i = 0; i < numVertices; ++i)
	{
		std::vector<FCDJointWeightPair> weights;
		if (skin)
		{
			FCDSkinControllerVertex* influences = skin->GetVertexInfluence(indicesPosition[i]);
			assert(influences != NULL);
			for (size_t j = 0; j < influences->GetPairCount(); ++j)
			{
				FCDJointWeightPair* pair = influences->GetPair(j);
				assert(pair != NULL);
				weights.push_back(*pair);
			}
			CanonicaliseWeights(weights);
		}

		std::vector<uv_pair_type> uvs;
		for (size_t set = 0; set < texcoordSources.size(); ++set)
		{
			const float* dataTexcoord = texcoordSources[set]->GetData();
			uint32 strideTexcoord = texcoordSources[set]->GetStride();

			uv_pair_type p;
			p.first = dataTexcoord[indicesTexcoord[i]*strideTexcoord];
			p.second = dataTexcoord[indicesTexcoord[i]*strideTexcoord + 1];
			uvs.push_back(p);
		}

		VertexData vtx (
			&dataPosition[indicesPosition[i]*stridePosition],
			&dataNormal  [indicesNormal  [i]*strideNormal],
			uvs,
			weights
		);
		size_t idx = inserter.add(vtx);
		indicesCombined.push_back((uint32)idx);
	}

	// TODO: rearrange indicesCombined (and rearrange vertexes to match) to use
	// the vertex cache efficiently
	// (<http://home.comcast.net/~tom_forsyth/papers/fast_vert_cache_opt.html> etc)

	FloatList newDataPosition;
	FloatList newDataNormal;
	FloatList newDataTexcoord;
	std::vector<std::vector<FCDJointWeightPair> > newWeightedMatches;

	for (size_t i = 0; i < vertexes.size(); ++i)
	{
		newDataPosition.push_back(vertexes[i].x);
		newDataPosition.push_back(vertexes[i].y);
		newDataPosition.push_back(vertexes[i].z);
		newDataNormal  .push_back(vertexes[i].nx);
		newDataNormal  .push_back(vertexes[i].ny);
		newDataNormal  .push_back(vertexes[i].nz);
		newWeightedMatches.push_back(vertexes[i].weights);
	}

	// (Slightly wasteful to duplicate this array so many times, but FCollada
	// doesn't seem to support multiple inputs with the same source data)
	inputPosition->SetIndices(&indicesCombined.front(), indicesCombined.size());
	inputNormal  ->SetIndices(&indicesCombined.front(), indicesCombined.size());
	inputTexcoord->SetIndices(&indicesCombined.front(), indicesCombined.size());

	for (size_t set = 0; set < texcoordSources.size(); ++set)
	{
		newDataTexcoord.clear();
		for (size_t i = 0; i < vertexes.size(); ++i)
		{
			newDataTexcoord.push_back(vertexes[i].uvs[set].first);
			newDataTexcoord.push_back(vertexes[i].uvs[set].second);
		}
		texcoordSources[set]->SetData(newDataTexcoord, 2);
	}

	sourcePosition->SetData(newDataPosition, 3);
	sourceNormal  ->SetData(newDataNormal,   3);

	if (skin)
	{
		skin->SetInfluenceCount(newWeightedMatches.size());
		for (size_t i = 0; i < newWeightedMatches.size(); ++i)
		{
			skin->GetVertexInfluence(i)->SetPairCount(0);
			for (size_t j = 0; j < newWeightedMatches[i].size(); ++j)
				skin->GetVertexInfluence(i)->AddPair(newWeightedMatches[i][j].jointIndex, newWeightedMatches[i][j].weight);
		}
	}
}
Exemplo n.º 13
0
xmlNode* FArchiveXML::WriteAnimationChannel(FCDObject* object, xmlNode* parentNode)
{
	FCDAnimationChannel* animationChannel = (FCDAnimationChannel*)object;

	FCDAnimationChannelData& data = FArchiveXML::documentLinkDataMap[animationChannel->GetDocument()].animationChannelData[animationChannel];
	//FUAssert(!data.targetPointer.empty(), NULL);
	fm::string baseId = FCDObjectWithId::CleanId(animationChannel->GetParent()->GetDaeId() + "_" + data.targetPointer);

	// Check for curve merging
	uint32 realCurveCount = 0;
	const FCDAnimationCurve* masterCurve = NULL;
	FCDAnimationCurveList mergingCurves;
	mergingCurves.resize(data.defaultValues.size());
	bool mergeCurves = true;
	size_t curveCount = animationChannel->GetCurveCount();
	for (size_t i = 0; i < curveCount; ++i)
	{
		const FCDAnimationCurve* curve = animationChannel->GetCurve(i);
		if (curve != NULL)
		{
			// Check that we have a default placement for this curve in the default value listing
			size_t dv;
			for (dv = 0; dv < data.defaultValues.size(); ++dv)
			{
				if (data.defaultValues[dv].curve == curve)
				{
					mergingCurves[dv] = const_cast<FCDAnimationCurve*>(curve);
					break;
				}
			}
			mergeCurves &= dv != data.defaultValues.size();

			// Check that the curves can be merged correctly.
			++realCurveCount;
			if (masterCurve == NULL)
			{
				masterCurve = curve;
			}
			else
			{
				// Check the infinity types, the keys and the interpolations.
				size_t curveKeyCount = curve->GetKeyCount();
				size_t masterKeyCount = masterCurve->GetKeyCount();
				mergeCurves &= masterKeyCount == curveKeyCount;
				if (!mergeCurves) break;

				for (size_t j = 0; j < curveKeyCount && mergeCurves; ++j)
				{
					const FCDAnimationKey* curveKey = curve->GetKey(j);
					const FCDAnimationKey* masterKey = masterCurve->GetKey(j);
					mergeCurves &= IsEquivalent(curveKey->input, masterKey->input);
					mergeCurves &= curveKey->interpolation == masterKey->interpolation;

					// Prevent curve having TCB interpolation from merging
					mergeCurves &= curveKey->interpolation != FUDaeInterpolation::TCB;
					mergeCurves &= masterKey->interpolation != FUDaeInterpolation::TCB;
				}
				if (!mergeCurves) break;

				mergeCurves &= curve->GetPostInfinity() == masterCurve->GetPostInfinity();
				mergeCurves &= curve->GetPreInfinity() == masterCurve->GetPreInfinity();
			}

			// Disallow the merging of any curves with a driver.
			mergeCurves &= !curve->HasDriver();
		}
	}

	if (mergeCurves && realCurveCount > 1)
	{
		// Prepare the list of default values
		FloatList values;
		values.reserve(data.defaultValues.size());
		for (FAXAnimationChannelDefaultValueList::iterator itDV = data.defaultValues.begin(); itDV != data.defaultValues.end(); ++itDV)
		{
			values.push_back((*itDV).defaultValue);
		}

		FUAssert(data.animatedValue != NULL, return parentNode);
		const char** qualifiers = new const char*[values.size()];
		memset(qualifiers, 0, sizeof(char*) * values.size());
		for (size_t i = 0; i < values.size() && i < data.animatedValue->GetValueCount(); ++i)
		{
			qualifiers[i] = data.animatedValue->GetQualifier(i);
		}

		// Merge and export the curves
		FCDAnimationMultiCurve* multiCurve = FCDAnimationCurveTools::MergeCurves(mergingCurves, values);
		FArchiveXML::WriteSourceFCDAnimationMultiCurve(multiCurve, parentNode, qualifiers, baseId);
		FArchiveXML::WriteSamplerFCDAnimationMultiCurve(multiCurve, parentNode, baseId);
		FArchiveXML::WriteChannelFCDAnimationMultiCurve(multiCurve, parentNode, baseId, data.targetPointer);
		SAFE_RELEASE(multiCurve);
	}