void DirectXRender::setTransform2d(IND_Matrix &pMatrix) {
	// ----- Return World Matrix (in DirectX format) -----
	float matArray[16];
	pMatrix.arrayRepresentation(matArray);
	D3DXMATRIX mMatWorld (matArray);

	// ----- Applies the transformation -----
	_info._device->SetTransform(D3DTS_WORLD, &mMatWorld);
}
void OpenGLES2Render::setTransform2d(IND_Matrix &pMatrix) {
	// ----- Applies the transformation -----
    float camMatrixArray [16];
    _cameraMatrix.arrayRepresentation(camMatrixArray);
    glLoadMatrixf(camMatrixArray);
    
    //Object transform
    float matrixArray [16];
    pMatrix.arrayRepresentation(matrixArray);
	glMultMatrixf(matrixArray);

	//Finally cache the change
	_modelToWorld = pMatrix;
}
void OpenGLES2Render::setTransform2d(int pX,
                                  int pY,
                                  float pAngleX,
                                  float pAngleY,
                                  float pAngleZ,
                                  float pScaleX,
                                  float pScaleY,
                                  int pAxisCalX,
                                  int pAxisCalY,
                                  bool pMirrorX,
                                  bool pMirrorY,
                                  int pWidth,
                                  int pHeight,
                                  IND_Matrix *pMatrix) {

	//Temporal holders for all accumulated transforms
	IND_Matrix totalTrans;
	_math.matrix4DSetIdentity(totalTrans);
	IND_Matrix temp;
	_math.matrix4DSetIdentity(temp);

	//Initialize to identity given matrix, if exists
	if (pMatrix) {
		_math.matrix4DSetIdentity(*pMatrix);
	}
    
	// Translations
	if (pX != 0 || pY != 0) {
		IND_Matrix trans;
		_math.matrix4DSetTranslation(trans,static_cast<float>(pX),static_cast<float>(pY),0.0f);
		_math.matrix4DMultiply(totalTrans,trans,temp);
		totalTrans = temp;
	}

	// Scaling
	if (pScaleX != 1.0f || pScaleY != 1.0f) {
		IND_Matrix scale;
		_math.matrix4DSetScale(scale,pScaleX,pScaleY,0.0f);
		_math.matrix4DMultiply(totalTrans,scale,temp);
		totalTrans = temp;
	}

	// Rotations
	if (pAngleX != 0.0f) {
		IND_Matrix angleX;
		_math.matrix4DSetRotationAroundAxis(angleX,pAngleX,IND_Vector3(1.0f,0.0f,0.0f));
		_math.matrix4DMultiply(totalTrans,angleX,temp);
		totalTrans = temp;
	}

	if (pAngleY != 0.0f) {
		IND_Matrix angleY;
		_math.matrix4DSetRotationAroundAxis(angleY,pAngleY,IND_Vector3(0.0f,1.0f,0.0f));
		_math.matrix4DMultiply(totalTrans,angleY,temp);
		totalTrans = temp;
	}

	if (pAngleZ != 0.0f) {
		IND_Matrix angleZ;
		_math.matrix4DSetRotationAroundAxis(angleZ,pAngleZ,IND_Vector3(0.0f,0.0f,1.0f));
		_math.matrix4DMultiply(totalTrans,angleZ,temp);
		totalTrans = temp;
	}

	// Hotspot - Add hotspot to make all transforms to be affected by it
	if (pAxisCalX != 0 || pAxisCalY != 0) {
		IND_Matrix hotspot;
		_math.matrix4DSetTranslation(hotspot,static_cast<float>(pAxisCalX),static_cast<float>(pAxisCalY),0.0f);
		_math.matrix4DMultiply(totalTrans,hotspot,temp);
		totalTrans = temp;
	}

    // Mirroring (180º rotations) and translation
	if (pMirrorX || pMirrorY) {
		//A mirror is a rotation in desired axis (the actual mirror) and a repositioning because rotation
		//also moves 'out of place' the entity translation-wise
		if (pMirrorX) {
			IND_Matrix mirrorX;
            //After rotation around origin, move back texture to correct place
            _math.matrix4DSetTranslation(mirrorX,
                                         static_cast<float>(pWidth),
                                         0.0f,
                                         0.0f);
			_math.matrix4DMultiply(totalTrans,mirrorX,temp);
			totalTrans = temp;
            
            //Rotate in y, to invert texture
			_math.matrix4DSetRotationAroundAxis(mirrorX,180.0f,IND_Vector3(0.0f,1.0f,0.0f));
			_math.matrix4DMultiply(totalTrans,mirrorX,temp);
			totalTrans = temp;
		}
        
		//A mirror is a rotation in desired axis (the actual mirror) and a repositioning because rotation
		//also moves 'out of place' the entity translation-wise
		if (pMirrorY) {
			IND_Matrix mirrorY;
            //After rotation around origin, move back texture to correct place
            _math.matrix4DSetTranslation(mirrorY,
                                         0.0f,
                                         static_cast<float>(pHeight),
                                         0.0f);
			_math.matrix4DMultiply(totalTrans,mirrorY,temp);
			totalTrans = temp;
            
            //Rotate in x, to invert texture
			_math.matrix4DSetRotationAroundAxis(mirrorY,180.0f,IND_Vector3(1.0f,0.0f,0.0f));
			_math.matrix4DMultiply(totalTrans,mirrorY,temp);
			totalTrans = temp;
		}
	}
	//Cache the change
	_modelToWorld = totalTrans;

	//Apply the changes to the GL matrix stack (model view)
    //Camera transform
    float camMatrixArray [16];
    _cameraMatrix.arrayRepresentation(camMatrixArray);
    glLoadMatrixf(camMatrixArray);
    
    //Actual object transform
    float matrixArray [16];
    totalTrans.arrayRepresentation(matrixArray);
	glMultMatrixf(matrixArray);

	// ----- Return World Matrix (in IndieLib format) ----
	//Transformations have been applied where needed
	if (pMatrix) {
		*pMatrix = totalTrans;
	}
}
void OpenGLRender::blitText(IND_Font *pFo,
                            char *pText,
                            int pX,
                            int pY,
                            int pOffset,
                            int pLineSpacing,
                            float pScaleX,
                            float pScaleY,
                            BYTE pR,
                            BYTE pG,
                            BYTE pB,
                            BYTE pA,
                            BYTE pFadeR,
                            BYTE pFadeG,
                            BYTE pFadeB,
                            BYTE pFadeA,
                            IND_Filter pLinearFilter,
                            IND_BlendingType pSo,
                            IND_BlendingType pDs,
                            IND_Align pAlign) {
	// ----- Transform -----
	bool correctParams = true;
	if(!pFo->getSurface()) {
		correctParams = false;
	}

	if (correctParams) {
		setTransform2d(pX, pY, 0, 0, 0, pScaleX, pScaleY, 0, 0, 0, 0, pFo->getSurface()->getWidthBlock(), pFo->getSurface()->getHeightBlock(), 0);
		setRainbow2d(pFo->_font._surface->getTypeInt(), 1, 0, 0, pLinearFilter, pR, pG, pB, pA, pFadeR, pFadeG, pFadeB, pFadeA, pSo, pDs);

		// ----- Drawing text   -----
		
		BYTE mChar1;
		BYTE mChar2;
		int mCont1 = 0;
		int mCont2 = 0;
		int mTranslationX = 0;
		int mTranslationY = 0;
		bool mErrorChar;    // Char that doesn't exist
		int mSentencePos;
		int mLongActualSentence;
		GLfloat mLineTransform[16];  //Maintains a transform inside the entity coord system
		GLfloat mEntityTransform[16]; //Maintains transform for the whole entity coord system
		mCont1 = 0;
		mChar1 = pText [mCont1++];

		//Store entity transform
		glGetFloatv(GL_MODELVIEW_MATRIX,mEntityTransform);

		//LOOP - Blit character by character
		while (mChar1 != 0) {
			// If it's a new line or it's the first line
			if (mChar1 == '\n' || mCont1 == 1) {
				// First line
				if (mCont1 == 1) {
					mSentencePos = 0;
				//Any other line
				} else {
					mSentencePos = mCont1;
				}

				// Set the alignment
				switch (pAlign) {
					case IND_CENTER: {
						mLongActualSentence = static_cast<int>(getLongInPixels(pFo, pText, mSentencePos, pOffset) * pScaleX);
						mTranslationX = (int)(mLongActualSentence / 2);
						break;
					}

					case IND_RIGHT: {
						mLongActualSentence = static_cast<int>(getLongInPixels(pFo, pText, mSentencePos, pOffset) * pScaleX);
						mTranslationX = (int)(mLongActualSentence);

						break;
					}

					case IND_LEFT: {
						break;
					}
				}

				//Load line transform matrix taking into account entity transform
				//This effectively resets transform to first character in the new line
				IND_Matrix transform;
				_math.matrix4DSetTranslation(transform, static_cast<float>(-mTranslationX), static_cast<float>(mTranslationY), 0.0f);
				transform.arrayRepresentation(mLineTransform);
				glLoadMatrixf(mEntityTransform);
				glMultMatrixf(mLineTransform);
				mTranslationY += static_cast<int>((pLineSpacing * pScaleY));
			} //Was first new line or first line

			// It's a normal character
			if (mChar1 != '\n') {

				mErrorChar = 0;
				mCont2 = 0;
				mChar2 = pFo->getLetters() [mCont2++]._letter;

				// Seek its location in the bitmap
				while (mChar2 != mChar1 && mCont2 < pFo->getNumChars()) {
					mChar2 = pFo->getLetters() [mCont2++]._letter;
				}
				if (mCont2  ==  pFo->getNumChars())
					mErrorChar = 1;

				mCont2--;
				if (!mErrorChar) {
//#warning lookout
					//mvTransformPresetState();  //Need to preset transform state, as the blit operation will reset the state!!!!
					blitRegionSurface(pFo->getSurface(),
									  pFo->getLetters() [mCont2]._offsetX + 1,
									  pFo->getLetters() [mCont2]._offsetY + 1,
									  pFo->getLetters() [mCont2]._widthChar - 1,
									  pFo->getLetters() [mCont2]._heightChar - 1);
				}

				//Displacement of the character.
				//Displacement transform accumulates for every character in the line
				float charTranslateX = ((pFo->getLetters() [mCont2]._widthChar) + pOffset) * pScaleX;
				glTranslatef(charTranslateX,0.0f,0.0f);
			}//Was normal character

			// Advance one character
			mChar1 = pText [mCont1++];
		}//LOOP END - Blit character by character

	}
}