//-----------------------------------------------------------------------
void DualQuaternionSkinning::addIndexedPositionWeight(Function* vsMain, int index,
								ParameterPtr& pWorldMatrix, ParameterPtr& pPositionTempParameter,
								ParameterPtr& pPositionRelatedOutputParam, int& funcCounter)
{
	Operand::OpMask indexMask = indexToMask(index);
	FunctionInvocation* curFuncInvocation;

	//multiply position with world matrix and put into temporary param
	curFuncInvocation = OGRE_NEW FunctionInvocation(SGX_FUNC_BLEND_WEIGHT, FFP_VS_TRANSFORM, funcCounter++);
	curFuncInvocation->pushOperand(mParamInWeights, Operand::OPS_IN, indexMask);
	curFuncInvocation->pushOperand(pWorldMatrix, Operand::OPS_IN);
	curFuncInvocation->pushOperand(pPositionTempParameter, Operand::OPS_OUT);
	vsMain->addAtomInstance(curFuncInvocation);

	//check if on first iteration
	if (index == 0)
	{
		//set the local param as the value of the world param
		curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_ASSIGN, FFP_VS_TRANSFORM, funcCounter++);
		curFuncInvocation->pushOperand(pPositionTempParameter, Operand::OPS_IN);
		curFuncInvocation->pushOperand(pPositionRelatedOutputParam, Operand::OPS_OUT);
		vsMain->addAtomInstance(curFuncInvocation);
	}
	else
	{
		//add the local param as the value of the world param
		curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_ADD, FFP_VS_TRANSFORM, funcCounter++);
		curFuncInvocation->pushOperand(pPositionTempParameter, Operand::OPS_IN);
		curFuncInvocation->pushOperand(pPositionRelatedOutputParam, Operand::OPS_IN);
		curFuncInvocation->pushOperand(pPositionRelatedOutputParam, Operand::OPS_OUT);
		vsMain->addAtomInstance(curFuncInvocation);
	}
}
//-----------------------------------------------------------------------
void HardwareSkinning::addIndexedPositionWeight(Function* vsMain, 
								int index, int& funcCounter)
{
	Operand::OpMask indexMask = indexToMask(index);
	
	FunctionInvocation* curFuncInvocation;

	//multiply position with world matrix and put into temporary param
	curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_TRANSFORM, FFP_VS_TRANSFORM, funcCounter++); 								
	curFuncInvocation->pushOperand(mParamInWorldMatrices, Operand::OPS_IN);
	curFuncInvocation->pushOperand(mParamInIndices, Operand::OPS_IN,  indexMask, 1);
	curFuncInvocation->pushOperand(mParamInPosition, Operand::OPS_IN);	
	curFuncInvocation->pushOperand(mParamTempFloat4, Operand::OPS_OUT, Operand::OPM_X | Operand::OPM_Y | Operand::OPM_Z);	
	vsMain->addAtomInstance(curFuncInvocation);	

	//set w value of temporary param to 1
	curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_ASSIGN, FFP_VS_TRANSFORM, funcCounter++); 								
	curFuncInvocation->pushOperand(ParameterFactory::createConstParamFloat(1.0f), Operand::OPS_IN);
	curFuncInvocation->pushOperand(mParamTempFloat4, Operand::OPS_OUT, Operand::OPM_W);	
	vsMain->addAtomInstance(curFuncInvocation);	

	//multiply temporary param with  weight
	curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_MODULATE, FFP_VS_TRANSFORM, funcCounter++); 								
	curFuncInvocation->pushOperand(mParamTempFloat4, Operand::OPS_IN);	
	curFuncInvocation->pushOperand(mParamInWeights, Operand::OPS_IN, indexMask);
	curFuncInvocation->pushOperand(mParamTempFloat4, Operand::OPS_OUT);	
	vsMain->addAtomInstance(curFuncInvocation);	

	//check if on first iteration
	if (index == 0)
	{
		//set the local param as the value of the world param
		curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_ASSIGN, FFP_VS_TRANSFORM, funcCounter++); 								
		curFuncInvocation->pushOperand(mParamTempFloat4, Operand::OPS_IN);
		curFuncInvocation->pushOperand(mParamLocalPositionWorld, Operand::OPS_OUT);	
		vsMain->addAtomInstance(curFuncInvocation);	
	}
	else
	{
		//add the local param as the value of the world param
		curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_ADD, FFP_VS_TRANSFORM, funcCounter++); 								
		curFuncInvocation->pushOperand(mParamLocalPositionWorld, Operand::OPS_IN);	
		curFuncInvocation->pushOperand(mParamLocalPositionWorld, Operand::OPS_OUT);	
		curFuncInvocation->pushOperand(mParamTempFloat4, Operand::OPS_IN);
		vsMain->addAtomInstance(curFuncInvocation);	
	}
}
//-----------------------------------------------------------------------
void HardwareSkinning::addIndexedNormalRelatedWeight(Function* vsMain,
								ParameterPtr& pNormalParam, 
								ParameterPtr& pNormalWorldRelatedParam, 
								int index, int& funcCounter)
{

	FunctionInvocation* curFuncInvocation;

	Operand::OpMask indexMask = indexToMask(index);
	
	//multiply position with world matrix and put into temporary param
	curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_TRANSFORM, FFP_VS_TRANSFORM, funcCounter++); 								
	curFuncInvocation->pushOperand(mParamInWorldMatrices, Operand::OPS_IN, Operand::OPM_ALL);
	curFuncInvocation->pushOperand(mParamInIndices, Operand::OPS_IN,  indexMask, 1);
	curFuncInvocation->pushOperand(pNormalParam, Operand::OPS_IN);	
	curFuncInvocation->pushOperand(mParamTempFloat3, Operand::OPS_OUT, Operand::OPM_X | Operand::OPM_Y | Operand::OPM_Z);	
	vsMain->addAtomInstance(curFuncInvocation);	

	//multiply temporary param with weight
	curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_MODULATE, FFP_VS_TRANSFORM, funcCounter++); 								
	curFuncInvocation->pushOperand(mParamTempFloat3, Operand::OPS_IN);	
	curFuncInvocation->pushOperand(mParamInWeights, Operand::OPS_IN, indexMask);
	curFuncInvocation->pushOperand(mParamTempFloat3, Operand::OPS_OUT);	
	vsMain->addAtomInstance(curFuncInvocation);	

	//check if on first iteration
	if (index == 0)
	{
		//set the local param as the value of the world normal
		curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_ASSIGN, FFP_VS_TRANSFORM, funcCounter++); 								
		curFuncInvocation->pushOperand(mParamTempFloat3, Operand::OPS_IN);
		curFuncInvocation->pushOperand(pNormalWorldRelatedParam, Operand::OPS_OUT);	
		vsMain->addAtomInstance(curFuncInvocation);	
	}
	else
	{
		//add the local param as the value of the world normal
		curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_ADD, FFP_VS_TRANSFORM, funcCounter++); 								
		curFuncInvocation->pushOperand(pNormalWorldRelatedParam, Operand::OPS_IN);	
		curFuncInvocation->pushOperand(pNormalWorldRelatedParam, Operand::OPS_OUT);	
		curFuncInvocation->pushOperand(mParamTempFloat3, Operand::OPS_IN);
		vsMain->addAtomInstance(curFuncInvocation);	
	}
}
int PressureSensor::flush(int handle)
{
    int id;

    switch (handle) {
    case ID_PRS:
        id = PRS;
    case ID_TMP:
        /* One-shot sensors must return -EINVAL */
        return -EINVAL;
    default:
        ALOGE("PressureSensor: unknown handle %d", handle);
        return -EINVAL;
    }

    if (!(mEnabled & indexToMask(id)))
        return -EINVAL;

    mPendingEventsFlushCount[id]++;

    return 0;
}
//-----------------------------------------------------------------------
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);
	}
}
int PressureSensor::readEvents(sensors_event_t* data, int count)
{
    if (count < 1)
        return -EINVAL;

    ssize_t n = mInputReader.fill(data_fd);
    if (n < 0)
        return n;

    int numEventReceived = 0;
    input_event const* event;

    for (int i = 0; i < NUM_SENSORS; i++) {
        if (!count)
            break;
        if (!mPendingEventsFlushCount[i])
            continue;
        sensors_meta_data_event_t flushEvent;
        flushEvent.version = META_DATA_VERSION;
        flushEvent.type = SENSOR_TYPE_META_DATA;
        flushEvent.meta_data.what = META_DATA_FLUSH_COMPLETE;
        flushEvent.meta_data.sensor = mPendingEvents[i].sensor;
        flushEvent.reserved0 = 0;
        flushEvent.timestamp = getTimestamp();
        *data++ = flushEvent;
        mPendingEventsFlushCount[i]--;
        count--;
        numEventReceived++;
    }

    while (count && mInputReader.readEvent(&event)) {
        int type = event->type;
        if (type == EV_REL) {
            float value = event->value;
            if (event->code == REL_HWHEEL || event->code == REL_X) {
                ALOGE("Pressure Sensor: Pressure! %d", event->value);
                if (mPressureActive) {
                    mPendingEventsMask |= 1 << PRS;
                    mPendingEvents[PRS].pressure = event-> value;
                }
            } else if (event->code == REL_DIAL || event->value == REL_Y) {
                ALOGE("Pressure Sensor: Sea Level! %d", event->value);
                mPendingEventsMask |= 1 << PRS;
                mSeaLevel = event->value;
            } else if (event->code == REL_WHEEL || event->code == REL_Z) {
                ALOGE("Pressure Sensor: Temperature! %d", event->value);
                if (mPressureActive) {
                    mPendingEventsMask |= 1 << PRS;
                    mPendingEvents[PRS].temperature = event->value;
                } else if (mTemperatureActive && mLastTemperature != event->value) {
                    mPendingEventsMask |= 1 << TMP;
                    mPendingEvents[TMP].temperature = event->value;
                    mLastTemperature = event->value;
                }
            } else {
                ALOGE("PressureSensor: unknown event (type=%d, code=%d)",
                      type, event->code);
            }

        } else if (type == EV_SYN) {
            for (int i = 0; count && mPendingEventsMask && i < NUM_SENSORS; i++) {
                if (mPendingEventsMask & (1 << i)) {
                    mPendingEventsMask &= ~(1 << i);
                    mPendingEvents[i].timestamp = timevalToNano(event->time);
                    if (mEnabled & indexToMask(i)) {
                        *data++ = mPendingEvents[i];
                        count--;
                        numEventReceived++;
                    }
                }
            }
        } else {
            ALOGE("PressureSensor: unknown event (type=%d, code=%d)",
                  type, event->code);
        }
        mInputReader.next();
    }

    return numEventReceived;
}