/*!***************************************************************************
 @fn       			MeasureText
 @param[out]		pfWidth				Width of the string in pixels
 @param[out]		pfHeight			Height of the string in pixels
 @param[in]			fFontSize			Font size
 @param[in]			sString				String to take the size of
 @brief      		Returns the size of a string in pixels.
*****************************************************************************/
void CPVRTPrint3D::MeasureText(
	float		* const pfWidth,
	float		* const pfHeight,
	float				fScale,
	const CPVRTArray<PVRTuint32>& utf32)
{
#if !defined (DISABLE_PRINT3D)
	if(utf32.GetSize() == 0) {
		if(pfWidth)
			*pfWidth = 0;
		if(pfHeight)
			*pfHeight = 0;
		return;
	}

	float fLength			= 0;
	float fMaxLength		= -1.0f;
	float fMaxHeight		= (float)m_uiNextLineH;
	PVRTuint32 txNextChar	= 0;
	PVRTuint32 uiIdx;
	for(PVRTuint32 uiIndex = 0; uiIndex < utf32.GetSize(); uiIndex++)
	{
		if(utf32[uiIndex] == 0x0D || utf32[uiIndex] == 0x0A)
		{
			if(fLength > fMaxLength)
				fMaxLength = fLength;

			fLength = 0;
			fMaxHeight += (float)m_uiNextLineH;
		}
		uiIdx = FindCharacter(utf32[uiIndex]);
		if(uiIdx == PVRTPRINT3D_INVALID_CHAR)		// No character found. Add a space.
		{
			fLength += m_uiSpaceWidth;
			continue;
		}

		float fKernOffset = 0;
		if ((uiIndex + 1) < utf32.GetSize())
		{
			txNextChar = utf32[uiIndex + 1];
			ApplyKerning(utf32[uiIndex], txNextChar, fKernOffset);
		}

		fLength += m_pCharMatrics[uiIdx].nAdv + fKernOffset;		// Add on this characters width
	}

	if(fMaxLength < 0.0f)		// Obviously no new line.
		fMaxLength = fLength;

	if(pfWidth)
		*pfWidth = fMaxLength * fScale;
	if(pfHeight)
		*pfHeight = fMaxHeight * fScale;
#endif
}
/*!***************************************************************************
 @Function			PVRTUnicodeUTF8ToUTF32
 @Input				pUTF8			A UTF8 string, which is null terminated.
 @Output			aUTF32			An array of Unicode code points.
 @Returns			Success or failure. 
 @Description		Decodes a UTF8-encoded string in to Unicode code points
					(UTF32). If pUTF8 is not null terminated, the results are 
					undefined.
*****************************************************************************/
EPVRTError PVRTUnicodeUTF8ToUTF32(const PVRTuint8* const pUTF8, CPVRTArray<PVRTuint32>& aUTF32)						
{
	unsigned int uiTailLen, uiIndex;
	unsigned int uiBytes = (unsigned int) strlen((const char*)pUTF8);
	PVRTuint32 c32;

	const PVRTuint8* pC = pUTF8;
	while(*pC)
	{
		// Quick optimisation for ASCII characters
		while(*pC && *pC < VALID_ASCII)
		{
			aUTF32.Append(*pC++);
		}
		// Done
		if(!*pC)			
			break;

		c32 = *pC++;
		uiTailLen = c_u8UTF8Lengths[c32];

		// Check for invalid tail length. Maximum 4 bytes for each UTF8 character.
		// Also check to make sure the tail length is inside the provided buffer.
		if(uiTailLen == 0 || (pC + uiTailLen > pUTF8 + uiBytes))
			return PVR_OVERFLOW;

		c32 &= (TAIL_MASK >> uiTailLen);	// Get the data out of the first byte. This depends on the length of the tail.

		// Get the data out of each tail byte
		uiIndex = 0;
		while(uiIndex < uiTailLen)
		{
			if((pC[uiIndex] & 0xC0) != 0x80)
				return PVR_FAIL;		// Invalid tail byte!

			c32 = (c32 << BYTES_PER_TAIL) + (pC[uiIndex] & TAIL_MASK);
			uiIndex++;
		}

		pC += uiIndex;

		// Check overlong values.
		if(c32 < c_u32MinVals[uiTailLen])
			return PVR_FAIL;		
		
		if(!CheckGenericUnicode(c32))
			return PVR_FAIL;

		// OK
		aUTF32.Append(c32);
	}

	return PVR_SUCCESS;
}
Beispiel #3
0
/*!****************************************************************************
 @Function		QuitApplication
 @Return		bool		true if no error occurred
 @Description	Code in QuitApplication() will be called by PVRShell once per
				run, just before exiting the program.
				If the rendering context is lost, QuitApplication() will
				not be called.
******************************************************************************/
bool OGLES2IntroducingPrint3D::QuitApplication()
{
	for(unsigned int uiIndex = 0; uiIndex < m_TextLines.GetSize(); ++uiIndex)
	{
		delete [] m_TextLines[uiIndex];
	}

	return true;
}
/*!****************************************************************************
 @Function		SetCollisionSpheres
 @Input			pSpheres	Pointer to an array of Sphere structs
 @Input			uiNumSpheres	The number of spheres
 @Description	Sets the physical model of the collision spheres and initializes them.
 ******************************************************************************/
bool ParticleSystemGPU::SetCollisionSpheres(const CPVRTArray<Sphere>& spheres)
{
	size_t size;
	if (size = spheres.GetSize())
	{
		glBindBuffer(GL_UNIFORM_BUFFER, m_SpheresUbo);
		glBufferData(GL_UNIFORM_BUFFER, size * sizeof(Sphere), &spheres[0], GL_STATIC_DRAW);
		glBindBufferBase(GL_UNIFORM_BUFFER, SPHERES_UBO_BINDING_INDEX, m_SpheresUbo);
		glBindBuffer(GL_UNIFORM_BUFFER, 0);
	}

	return true;
}
/*!***************************************************************************
 @Function			PVRTUnicodeUTF16ToUTF32
 @Input				pUTF16			A UTF16 string, which is null terminated.
 @Output			aUTF32			An array of Unicode code points.
 @Returns			Success or failure. 
 @Description		Decodes a UTF16-encoded string in to Unicode code points
					(UTF32). If pUTF16 is not null terminated, the results are 
					undefined.
*****************************************************************************/
EPVRTError PVRTUnicodeUTF16ToUTF32(const PVRTuint16* const pUTF16, CPVRTArray<PVRTuint32>& aUTF32)
{
	const PVRTuint16* pC = pUTF16;

	// Determine the number of shorts
	while(*++pC && (pC - pUTF16) < MAX_LEN);
	unsigned int uiBufferLen = (unsigned int) (pC - pUTF16);

	if(uiBufferLen == MAX_LEN)
		return PVR_OVERFLOW;		// Probably not NULL terminated.	

	// Reset to start.
	pC = pUTF16;

	PVRTuint32 c32;
	while(*pC)
	{
		// Straight copy. We'll check for surrogate pairs next...
		c32 = *pC++;

		// Check surrogate pair
		if(c32 >= UTF16_SURG_H_MARK && c32 <= UTF16_SURG_H_END)
		{
			// Make sure the next 2 bytes are in range...
			if(pC + 1 > pUTF16 + uiBufferLen || *pC == 0)
				return PVR_OVERFLOW;

			// Check that the next value is in the low surrogate range
			if(*pC < UTF16_SURG_L_MARK || *pC > UTF16_SURG_L_END)
				return PVR_FAIL;

			// Decode
			c32 = ((c32 - UTF16_SURG_H_MARK) << 10) + (*pC - UTF16_SURG_L_MARK) + 0x10000;
			pC++;
		}

		if(!CheckGenericUnicode(c32))
			return PVR_FAIL;

		// OK
		aUTF32.Append(c32);
	}

	return PVR_SUCCESS;
}
std::string NSStringFromSPVRTPFXParserEffect( PFXClassPtr pSPVRTPFXParserEffect ) 
{
	SPVRTPFXParserEffect* pfxEffect = (SPVRTPFXParserEffect*)pSPVRTPFXParserEffect;
	std::string desc = "";
	desc += CC3String::stringWithFormat( (char*)"SPVRTPFXParserEffect" );
	desc += CC3String::stringWithFormat( (char*)" named %s", pfxEffect->Name.c_str() );
	desc += CC3String::stringWithFormat( (char*)"\n\tvertex shader: %s", pfxEffect->VertexShaderName.c_str() );
	desc += CC3String::stringWithFormat( (char*)"\n\tfragment shader: %s", pfxEffect->FragmentShaderName.c_str() );
	
	CPVRTArray<SPVRTPFXParserSemantic> attributes = pfxEffect->Attributes;
	GLuint attrCount = attributes.GetSize();
	desc += CC3String::stringWithFormat( (char*)"\n\twith %d attributes:", attrCount );
	for(GLuint i = 0; i < attrCount; i++) {
		desc += CC3String::stringWithFormat( (char*)"\n\t\t%s:", NSStringFromSPVRTPFXParserSemantic(&attributes[i], "attribute").c_str() );
	}

	CPVRTArray<SPVRTPFXParserSemantic> uniforms = pfxEffect->Uniforms;
	GLuint uniformCount = uniforms.GetSize();
	desc += CC3String::stringWithFormat( (char*)"\n\twith %d uniforms:", uniformCount );
	for(GLuint i = 0; i < uniformCount; i++) {
		desc += CC3String::stringWithFormat( (char*)"\n\t\t%s:", NSStringFromSPVRTPFXParserSemantic(&uniforms[i], "uniform").c_str() );
	}
	
	CPVRTArray<SPVRTPFXParserEffectTexture> textures = pfxEffect->Textures;
	GLuint texCount = textures.GetSize();
	desc += CC3String::stringWithFormat( (char*)"\n\twith %d textures:", texCount );
	for(GLuint i = 0; i < texCount; i++) {
		desc += CC3String::stringWithFormat( (char*)"\n\t\t%s:", NSStringFromSPVRTPFXParserEffectTexture(&textures[i]).c_str() );
	}
	
	CPVRTArray<SPVRTTargetPair> targets = pfxEffect->Targets;
	GLuint targCount = targets.GetSize();
	desc += CC3String::stringWithFormat( (char*)"\n\twith %d targets:", targCount );
	for(GLuint i = 0; i < targCount; i++) {
		desc += CC3String::stringWithFormat( (char*)"\n\t\ttarget named %s of type %s", targets[i].TargetName.c_str(), targets[i].BufferType.c_str() );
	}

	desc += CC3String::stringWithFormat( (char*)"\n\tannotation: %s", pfxEffect->Annotation.c_str() );
	return desc;
}
Beispiel #7
0
/*!***************************************************************************
@Function		Print3D
@Input			fPosX		X Position
@Input			fPosY		Y Position
@Input			fScale		Text scale
@Input			Colour		ARGB colour
@Input			UTF32		Array of UTF32 characters
@Input			bUpdate		Whether to update the vertices
@Return			EPVRTError	Success of failure
@Description	Takes an array of UTF32 characters and generates the required mesh.
*****************************************************************************/
EPVRTError CPVRTPrint3D::Print3D(float fPosX, float fPosY, const float fScale, unsigned int Colour, const CPVRTArray<PVRTuint32>& UTF32, bool bUpdate)
{
	// No textures! so... no window
	if (!m_bTexturesSet)
	{
		PVRTErrorOutputDebug("DisplayWindow : You must call CPVRTPrint3D::SetTextures(...) before using this function.\n");
		return PVR_FAIL;
	}

	// nothing to be drawn
	if(UTF32.GetSize() == 0)
		return PVR_FAIL;

	// Adjust input parameters
	if(!m_bUsingProjection)
	{
		fPosX =  (float)((int)(fPosX * (640.0f/100.0f)));
		fPosY = -(float)((int)(fPosY * (480.0f/100.0f)));
	}

	// Create Vertex Buffer (only if it doesn't exist)
	if(m_pPrint3dVtx == 0)
	{
		m_pPrint3dVtx = (SPVRTPrint3DAPIVertex*)malloc(MAX_LETTERS*4*sizeof(SPVRTPrint3DAPIVertex));

		if(!m_pPrint3dVtx)
			return PVR_FAIL;
	}

	// Fill up our buffer
	if(bUpdate)
		m_nCachedNumVerts = UpdateLine(0.0f, fPosX, fPosY, fScale, Colour, UTF32, m_pPrint3dVtx);

	// Draw the text
	if(!DrawLine(m_pPrint3dVtx, m_nCachedNumVerts))
		return PVR_FAIL;

	return PVR_SUCCESS;
}
Beispiel #8
0
/*!***************************************************************************
 @Function			UpdateLine
 @Description
*****************************************************************************/
unsigned int CPVRTPrint3D::UpdateLine(const float fZPos, float XPos, float YPos, const float fScale, const unsigned int Colour, const CPVRTArray<PVRTuint32>& Text, SPVRTPrint3DAPIVertex * const pVertices)
{
	/* Nothing to update */
	if (Text.GetSize() == 0) 
		return 0;

	if(!m_bUsingProjection)
	{
		XPos *= m_fScreenScale[0];
		YPos *= m_fScreenScale[1];
	}

	YPos -= PVRTMakeWhole(m_uiAscent * fScale);

	float fPreXPos	= XPos;		// The original offset (after screen scale modification) of the X coordinate.

	float		fKernOffset;
	float		fAOff;
	float		fYOffset;
	unsigned int VertexCount = 0;
	PVRTint32 NextChar;

	unsigned int uiNumCharsInString = Text.GetSize();
	for(unsigned int uiIndex = 0; uiIndex < uiNumCharsInString; uiIndex++)
	{
		if(uiIndex > MAX_LETTERS) 
			break;

		// Newline
		if(Text[uiIndex] == 0x0A)
		{
			XPos = fPreXPos;
			YPos -= PVRTMakeWhole(m_uiNextLineH * fScale);
			continue;
		}

		// Get the character
		PVRTuint32 uiIdx = FindCharacter(Text[uiIndex]);

		// Not found. Add a space.
		if(uiIdx == PVRTPRINT3D_INVALID_CHAR)		// No character found. Add a space.
		{
			XPos += PVRTMakeWhole(m_uiSpaceWidth * fScale);
			continue;
		}

		fKernOffset = 0;
		fYOffset	= PVRTMakeWhole(m_pYOffsets[uiIdx] * fScale);
		fAOff		= PVRTMakeWhole(m_pCharMatrics[uiIdx].nXOff * fScale);					// The A offset. Could include overhang or underhang.
		if(uiIndex < uiNumCharsInString - 1)
		{
			NextChar = Text[uiIndex + 1];
			ApplyKerning(Text[uiIndex], NextChar, fKernOffset);
		}

		/* Filling vertex data */
		pVertices[VertexCount+0].sx		= f2vt(XPos + fAOff + 0.0f);
		pVertices[VertexCount+0].sy		= f2vt(YPos + fYOffset + 0.0f);
		pVertices[VertexCount+0].sz		= f2vt(fZPos);
		pVertices[VertexCount+0].rhw	= f2vt(1.0f);
		pVertices[VertexCount+0].tu		= f2vt(m_pUVs[uiIdx].fUL);
		pVertices[VertexCount+0].tv		= f2vt(m_pUVs[uiIdx].fVT);

		pVertices[VertexCount+1].sx		= f2vt(XPos + fAOff + PVRTMakeWhole(m_pRects[uiIdx].nW * fScale));
		pVertices[VertexCount+1].sy		= f2vt(YPos + fYOffset + 0.0f);
		pVertices[VertexCount+1].sz		= f2vt(fZPos);
		pVertices[VertexCount+1].rhw	= f2vt(1.0f);
		pVertices[VertexCount+1].tu		= f2vt(m_pUVs[uiIdx].fUR);
		pVertices[VertexCount+1].tv		= f2vt(m_pUVs[uiIdx].fVT);

		pVertices[VertexCount+2].sx		= f2vt(XPos + fAOff + 0.0f);
		pVertices[VertexCount+2].sy		= f2vt(YPos + fYOffset - PVRTMakeWhole(m_pRects[uiIdx].nH * fScale));
		pVertices[VertexCount+2].sz		= f2vt(fZPos);
		pVertices[VertexCount+2].rhw	= f2vt(1.0f);
		pVertices[VertexCount+2].tu		= f2vt(m_pUVs[uiIdx].fUL);
		pVertices[VertexCount+2].tv		= f2vt(m_pUVs[uiIdx].fVB);

		pVertices[VertexCount+3].sx		= f2vt(XPos + fAOff + PVRTMakeWhole(m_pRects[uiIdx].nW * fScale));
		pVertices[VertexCount+3].sy		= f2vt(YPos + fYOffset - PVRTMakeWhole(m_pRects[uiIdx].nH * fScale));
		pVertices[VertexCount+3].sz		= f2vt(fZPos);
		pVertices[VertexCount+3].rhw	= f2vt(1.0f);
		pVertices[VertexCount+3].tu		= f2vt(m_pUVs[uiIdx].fUR);
		pVertices[VertexCount+3].tv		= f2vt(m_pUVs[uiIdx].fVB);

		pVertices[VertexCount+0].color	= Colour;
		pVertices[VertexCount+1].color	= Colour;
		pVertices[VertexCount+2].color	= Colour;
		pVertices[VertexCount+3].color	= Colour;

		XPos = XPos + PVRTMakeWhole((m_pCharMatrics[uiIdx].nAdv + fKernOffset) * fScale);		// Add on this characters width
		VertexCount += 4;
	}

	return VertexCount;
}
Beispiel #9
0
/*!***************************************************************************
@Function		RenderText
@Description	Draws the 3D text and scrolls in to the screen.
*****************************************************************************/
void OGLES2IntroducingPrint3D::RenderText()
{
	float fAspect = (float)PVRShellGet(prefWidth) / (float)PVRShellGet(prefHeight);
	bool bRotate = PVRShellGet(prefIsRotated) && PVRShellGet(prefFullScreen);

	// Calculate the frame delta.
	unsigned long ulNow = PVRShellGetTime();
	if(m_ulPrevFrameT == 0)	m_ulPrevFrameT = ulNow;
	float fDT = (ulNow - m_ulPrevFrameT) * 0.001f;
	m_ulPrevFrameT = ulNow;
		
	// Calculate the FPS scale.
	float fFPSScale = fDT / c_fTargetFPS;
		
	// Move the text. Progressively speed up.
	float fSpeedInc = 0.0f;
	if(m_fTextOffset > 0.0f)
		fSpeedInc = m_fTextOffset / TEXT_END_Y;
	m_fTextOffset += (0.75f + (1.0f * fSpeedInc)) * fFPSScale;
	if(m_fTextOffset > TEXT_END_Y)
		m_fTextOffset = TEXT_START_Y;

	PVRTMat4 mProjection = PVRTMat4::PerspectiveFovRH(0.7f, fAspect, 1.0f, 2000.0f, PVRTMat4::OGL, bRotate);
	PVRTMat4 mScale      = PVRTMat4::Scale(PVRTVec3(1.0f, -1.0f, 1.0f)); 
	PVRTMat4 mCamera     = PVRTMat4::LookAtRH(PVRTVec3(0.0f, -900.0f, 700.0f), PVRTVec3(0.0f,-200.0f,0.0f), PVRTVec3(0.0f,1.0f,0.0f));
	PVRTMat4 mTrans		 = PVRTMat4::Translation(PVRTVec3(0.0f, m_fTextOffset, 0.0f));
	PVRTMat4 mModelView  = mCamera * mTrans;
	float fStrWidth = 0.0f;

	/*
		Print3D can optionally be provided with user-defined projection and model-view matrices
		which allow custom layout of text. Here we are proving both a projection and model-view
		matrix. The projection matrix specified here uses perspective projection which will
		provide the 3D effect. The model-view matrix positions the the text in world space
		providing the 'camera' position and the scrolling of the text.
	*/
	m_CentralText.SetProjection(mProjection);
	m_CentralText.SetModelView(mModelView);

	/*
		The previous method (RenderTitle()) explains the following functions in more detail
		however put simply, we are looping the entire array of loaded text which is encoded
		in UTF-8. Print3D batches this internally and the call to Flush() will render the
		text to the frame buffer. We are also fading out the text over a certain distance.
	*/
	float fPos, fFade;
	unsigned int uiCol;
	for(unsigned int uiIndex = 0; uiIndex < m_TextLines.GetSize(); ++uiIndex)
	{
		fPos = (m_fTextOffset - (uiIndex * 36.0f));
		fFade = 1.0f;
		if(fPos > TEXT_FADE_START)
		{
			fFade = PVRTClamp(1.0f - ((fPos - TEXT_FADE_START) / (TEXT_FADE_END - TEXT_FADE_START)), 0.0f, 1.0f);
		}

		uiCol = (((unsigned int)(fFade * 255)) << 24) | 0x00FFFF;

		m_CentralText.MeasureText(&fStrWidth, NULL, 1.0f, (const char*)m_TextLines[uiIndex]);
		m_CentralText.Print3D(-(fStrWidth*0.5f), -(uiIndex * 36.0f), 1.0f, uiCol, (const char*)m_TextLines[uiIndex]);
	}

	m_CentralText.Flush();
}
Beispiel #10
0
/*!****************************************************************************
 @Function		InitApplication
 @Return		bool		true if no error occurred
 @Description	Code in InitApplication() will be called by PVRShell once per
				run, before the rendering context is created.
				Used to initialize variables that are not dependent on it
				(e.g. external modules, loading meshes, etc.)
				If the rendering context is lost, InitApplication() will
				not be called again.
******************************************************************************/
bool OGLES2IntroducingPrint3D::InitApplication()
{
	/*
		CPVRTResourceFile is a resource file helper class. Resource files can
		be placed on disk next to the executable or in a platform dependent
		read path. We need to tell the class where that read path is.
		Additionally, it is possible to wrap files into cpp modules and
		link them directly into the executable. In this case no path will be
		used. Files on disk will override "memory files".
	*/

	// Get and set the read path for content files
	CPVRTResourceFile::SetReadPath((char*)PVRShellGet(prefReadPath));

	
	/* 
		Get and set the load/release functions for loading external files.
		In the majority of cases the PVRShell will return NULL function pointers implying that
		nothing special is required to load external files.
	*/
	CPVRTResourceFile::SetLoadReleaseFunctions(PVRShellGet(prefLoadFileFunc), PVRShellGet(prefReleaseFileFunc));

	/*
		Because the C++ standard states that only ASCII characters are valid in compiled code,
		we are instead using an external resource file which contains all of the text to be
		rendered. This allows complete control over the encoding of the resource file which
		in this case is encoded as UTF-8.		
	*/
	CPVRTResourceFile TextResource(c_szResTextFile);
	if(!TextResource.IsOpen())
	{
		PVRShellSet(prefExitMessage, "ERROR: Failed to load text resource file!");
		return false;
	}

	/*
		The following code simply pulls out each line in the resource file and adds it
		to an array so we can render each line separately.
	*/
	const PVRTuint8* pStart = (PVRTuint8*)TextResource.DataPtr();
	const PVRTuint8* pC = pStart;	
	while(*pC && ((unsigned int)(pC - pStart) < TextResource.Size()))
	{
		// Read how many characters on this line.
		const PVRTuint8* pLStart = pC;
		while(*pC && *pC != '\n') pC++;

		unsigned int uiDataLen = (unsigned int) (pC - pLStart + 1);
		PVRTuint8* pLineData = new PVRTuint8[uiDataLen + 1];
		memset(pLineData, 0, uiDataLen + 1);
		pC = pLStart;

		unsigned int uiIndex;
		for(uiIndex = 0; uiIndex < uiDataLen; ++uiIndex)
			pLineData[uiIndex] = pC[uiIndex];
	
		pC += uiDataLen;
		m_TextLines.Append(pLineData);
	}

	m_fTextOffset  = TEXT_START_Y;
	m_ulPrevFrameT = 0;
	m_eTitleLang   = eLang_English; 

	return true;
}