//-----------------------------------------------------------------------
void HardwareSkinning::addNormalRelatedCalculations(Function* vsMain,
								ParameterPtr& pNormalRelatedParam, 
								ParameterPtr& pNormalWorldRelatedParam, 
								int& funcCounter)
{
	FunctionInvocation* curFuncInvocation;
	
	if (mDoBoneCalculations == true)
	{
		//set functions to calculate world normal
		for(int i = 0 ; i < getWeightCount() ; ++i)
		{
			addIndexedNormalRelatedWeight(vsMain, pNormalRelatedParam, pNormalWorldRelatedParam, i, funcCounter);
		}

		//update back the original position relative to the object
		curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_TRANSFORM, FFP_VS_TRANSFORM, funcCounter++); 								
		curFuncInvocation->pushOperand(mParamInInvWorldMatrix, Operand::OPS_IN);
		curFuncInvocation->pushOperand(pNormalWorldRelatedParam, Operand::OPS_IN);
		curFuncInvocation->pushOperand(pNormalRelatedParam, Operand::OPS_OUT);
		vsMain->addAtomInstance(curFuncInvocation);	
	}
	else
	{
		//update from object to world space
		curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_TRANSFORM, FFP_VS_TRANSFORM, funcCounter++); 								
		curFuncInvocation->pushOperand(mParamInWorldMatrix, Operand::OPS_IN);
		curFuncInvocation->pushOperand(pNormalRelatedParam, Operand::OPS_IN);
		curFuncInvocation->pushOperand(pNormalWorldRelatedParam, Operand::OPS_OUT);
		vsMain->addAtomInstance(curFuncInvocation);	
	}

}
//-----------------------------------------------------------------------
void HardwareSkinning::addPositionCalculations(Function* vsMain, int& funcCounter)
{
	FunctionInvocation* curFuncInvocation = NULL;	
	
	if (mDoBoneCalculations == true)
	{
		//set functions to calculate world position
		for(int i = 0 ; i < getWeightCount() ; ++i)
		{
			addIndexedPositionWeight(vsMain, i, funcCounter);
		}
		
		//update back the original position relative to the object
		curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_TRANSFORM, FFP_VS_TRANSFORM, funcCounter++); 								
		curFuncInvocation->pushOperand(mParamInInvWorldMatrix, Operand::OPS_IN);
		curFuncInvocation->pushOperand(mParamLocalPositionWorld, Operand::OPS_IN);
		curFuncInvocation->pushOperand(mParamInPosition, Operand::OPS_OUT);
		vsMain->addAtomInstance(curFuncInvocation);	

		//update the projective position thereby filling the transform stage role
		curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_TRANSFORM, FFP_VS_TRANSFORM, funcCounter++); 								
		curFuncInvocation->pushOperand(mParamInViewProjMatrix, Operand::OPS_IN);
		curFuncInvocation->pushOperand(mParamLocalPositionWorld, Operand::OPS_IN);
		curFuncInvocation->pushOperand(mParamOutPositionProj, Operand::OPS_OUT);
		vsMain->addAtomInstance(curFuncInvocation);	
	}
	else
	{
		//update from object to world space
		curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_TRANSFORM, FFP_VS_TRANSFORM, funcCounter++); 								
		curFuncInvocation->pushOperand(mParamInWorldMatrix, Operand::OPS_IN);
		curFuncInvocation->pushOperand(mParamInPosition, Operand::OPS_IN);
		curFuncInvocation->pushOperand(mParamLocalPositionWorld, Operand::OPS_OUT);
		vsMain->addAtomInstance(curFuncInvocation);	

		//update from object to projective space
		curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_TRANSFORM, FFP_VS_TRANSFORM, funcCounter++); 								
		curFuncInvocation->pushOperand(mParamInWorldViewProjMatrix, Operand::OPS_IN);
		curFuncInvocation->pushOperand(mParamInPosition, Operand::OPS_IN);
		curFuncInvocation->pushOperand(mParamOutPositionProj, Operand::OPS_OUT);
		vsMain->addAtomInstance(curFuncInvocation);	
	}
}
//-----------------------------------------------------------------------
void DualQuaternionSkinning::addPositionCalculations(Function* vsMain, int& funcCounter)
{
	FunctionInvocation* curFuncInvocation = NULL;

	if (mDoBoneCalculations == true)
	{
		if(mScalingShearingSupport)
		{
			//Construct a scaling and shearing matrix based on the blend weights
			for(int i = 0 ; i < getWeightCount() ; ++i)
			{
				//Assign the local param based on the current index of the scaling and shearing matrices
				curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_ASSIGN, FFP_VS_TRANSFORM, funcCounter++);
				curFuncInvocation->pushOperand(mParamInScaleShearMatrices, Operand::OPS_IN);
				curFuncInvocation->pushOperand(mParamInIndices, Operand::OPS_IN,  indexToMask(i), 1);
				curFuncInvocation->pushOperand(mParamTempFloat3x4, Operand::OPS_OUT);
				vsMain->addAtomInstance(curFuncInvocation);

				//Calculate the resultant scaling and shearing matrix based on the weights given
				addIndexedPositionWeight(vsMain, i, mParamTempFloat3x4, mParamTempFloat3x4, mParamBlendS, funcCounter);
			}

			//Transform the position based by the scaling and shearing matrix
			curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_TRANSFORM, FFP_VS_TRANSFORM, funcCounter++);
			curFuncInvocation->pushOperand(mParamBlendS, Operand::OPS_IN);
			curFuncInvocation->pushOperand(mParamInPosition, Operand::OPS_IN, Operand::OPM_XYZ);
			curFuncInvocation->pushOperand(mParamLocalBlendPosition, Operand::OPS_OUT);
			vsMain->addAtomInstance(curFuncInvocation);
		}
		else
		{
			//Assign the input position to the local blended position
			curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_ASSIGN, FFP_VS_TRANSFORM, funcCounter++);
			curFuncInvocation->pushOperand(mParamInPosition, Operand::OPS_IN, Operand::OPM_XYZ);
			curFuncInvocation->pushOperand(mParamLocalBlendPosition, Operand::OPS_OUT);
			vsMain->addAtomInstance(curFuncInvocation);
		}
		
		//Set functions to calculate world position
		for(int i = 0 ; i < getWeightCount() ; ++i)
		{
			//Set the index of the matrix
			curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_ASSIGN, FFP_VS_TRANSFORM, funcCounter++);
			curFuncInvocation->pushOperand(mParamInIndices, Operand::OPS_IN,  indexToMask(i));
			curFuncInvocation->pushOperand(mParamIndex1, Operand::OPS_OUT);
			vsMain->addAtomInstance(curFuncInvocation);
			
			//Multiply the index by 2
			curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_MODULATE, FFP_VS_TRANSFORM, funcCounter++);
			curFuncInvocation->pushOperand(ParameterFactory::createConstParamFloat(2.0f), Operand::OPS_IN);
			curFuncInvocation->pushOperand(mParamIndex1, Operand::OPS_IN);
			curFuncInvocation->pushOperand(mParamIndex1, Operand::OPS_OUT);
			vsMain->addAtomInstance(curFuncInvocation);
			
			//Add 1 to the index and assign as the second row's index
			curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_ADD, FFP_VS_TRANSFORM, funcCounter++);
			curFuncInvocation->pushOperand(ParameterFactory::createConstParamFloat(1.0f), Operand::OPS_IN);
			curFuncInvocation->pushOperand(mParamIndex1, Operand::OPS_IN);
			curFuncInvocation->pushOperand(mParamIndex2, Operand::OPS_OUT);
			vsMain->addAtomInstance(curFuncInvocation);
			
			//Build the dual quaternion matrix
			curFuncInvocation = OGRE_NEW FunctionInvocation(SGX_FUNC_BUILD_DUAL_QUATERNION_MATRIX, FFP_VS_TRANSFORM, funcCounter++);
			curFuncInvocation->pushOperand(mParamInWorldMatrices, Operand::OPS_IN);
			curFuncInvocation->pushOperand(mParamIndex1, Operand::OPS_IN,  Operand::OPM_ALL, 1);
			curFuncInvocation->pushOperand(mParamInWorldMatrices, Operand::OPS_IN);
			curFuncInvocation->pushOperand(mParamIndex2, Operand::OPS_IN,  Operand::OPM_ALL, 1);
			curFuncInvocation->pushOperand(mParamTempFloat2x4, Operand::OPS_OUT);
			vsMain->addAtomInstance(curFuncInvocation);
			
			//Adjust the podalities of the dual quaternions
			if(mCorrectAntipodalityHandling)
			{	
				adjustForCorrectAntipodality(vsMain, i, funcCounter, mParamTempFloat2x4);
			}

			//Calculate the resultant dual quaternion based on the weights given
			addIndexedPositionWeight(vsMain, i, mParamTempFloat2x4, mParamTempFloat2x4, mParamBlendDQ, funcCounter);
		}

		//Normalize the dual quaternion
		curFuncInvocation = OGRE_NEW FunctionInvocation(SGX_FUNC_NORMALIZE_DUAL_QUATERNION, FFP_VS_TRANSFORM, funcCounter++);
		curFuncInvocation->pushOperand(mParamBlendDQ, Operand::OPS_INOUT);
		vsMain->addAtomInstance(curFuncInvocation);

		//Calculate the blend position
		curFuncInvocation = OGRE_NEW FunctionInvocation(SGX_FUNC_CALCULATE_BLEND_POSITION, FFP_VS_TRANSFORM, funcCounter++);
		curFuncInvocation->pushOperand(mParamLocalBlendPosition, Operand::OPS_IN);
		curFuncInvocation->pushOperand(mParamBlendDQ, Operand::OPS_IN);
		curFuncInvocation->pushOperand(mParamTempFloat4, Operand::OPS_OUT);
		vsMain->addAtomInstance(curFuncInvocation);

		//Update from object to projective space
		curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_TRANSFORM, FFP_VS_TRANSFORM, funcCounter++);
		curFuncInvocation->pushOperand(mParamInViewProjMatrix, Operand::OPS_IN);
		curFuncInvocation->pushOperand(mParamTempFloat4, Operand::OPS_IN);
		curFuncInvocation->pushOperand(mParamOutPositionProj, Operand::OPS_OUT);
		vsMain->addAtomInstance(curFuncInvocation);
	}
	else
	{
		//update from object to world space
		curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_TRANSFORM, FFP_VS_TRANSFORM, funcCounter++);
		curFuncInvocation->pushOperand(mParamInWorldMatrix, Operand::OPS_IN);
		curFuncInvocation->pushOperand(mParamInPosition, Operand::OPS_IN);
		curFuncInvocation->pushOperand(mParamLocalPositionWorld, Operand::OPS_OUT);
		vsMain->addAtomInstance(curFuncInvocation);

		//update from object to projective space
		curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_TRANSFORM, FFP_VS_TRANSFORM, funcCounter++);
		curFuncInvocation->pushOperand(mParamInWorldViewProjMatrix, Operand::OPS_IN);
		curFuncInvocation->pushOperand(mParamInPosition, Operand::OPS_IN);
		curFuncInvocation->pushOperand(mParamOutPositionProj, Operand::OPS_OUT);
		vsMain->addAtomInstance(curFuncInvocation);
	}
}