Ejemplo n.º 1
0
//------------------------------------------------------------------------------------
// прорисовка фонта в 3д пространстве
//------------------------------------------------------------------------------------
void vw_DrawFont3D(float X, float Y, float Z, const char *Text, ...)
{

	if (Text == 0) return;

	// смотрим значения параметров в строке
	char	text[1024];
	va_list		ap;
	va_start(ap, Text);
	vsprintf(text, Text, ap);
	va_end(ap);
	// в text уже полная строка
	if (strlen(text) == 0) return;
	// прорисовка текста
	const char *textdraw = text;


	float Xstart = 0.0f;
	// сразу определяем "базовую" ширину пробела
	float SpaceWidth = vw_FindFontCharByUTF32(0x020)->AdvanceX;
	// чтобы было более читаемо - делаем пробел не менее 2/3 ширины
	if (SpaceWidth < (InternalFontSize * 0.65f)) SpaceWidth = InternalFontSize * 0.65f;

	textdraw = text;


	// для отрисовки
	eTexture* CurrentTexture = 0;
	int k=0;
	// буфер для последовательности RI_QUADS
	// войдет RI_2f_XY | RI_2f_TEX
#ifdef USE_GLES
	float tmp[(2+2)*6*strlen(textdraw)];
#else
	float tmp[(2+2)*4*strlen(textdraw)];
#endif

	// установка свойств текстуры
	vw_SetTextureBlend(true, RI_BLEND_SRCALPHA, RI_BLEND_INVSRCALPHA);
	// всегда стаим белый цвет
	vw_SetColor(1.0f, 1.0f, 1.0f, 1.0f);

	vw_PushMatrix();

	vw_Translate(VECTOR3D(X, Y, Z));
	VECTOR3D CurrentCameraRotation;
	vw_GetCameraRotation(&CurrentCameraRotation);

	// поворачиваем к камере
	vw_Rotate(CurrentCameraRotation.y, 0.0f, 1.0f, 0.0f);
	vw_Rotate(CurrentCameraRotation.x, 1.0f, 0.0f, 0.0f);


	// прорисовываем все символы
	while (strlen(textdraw) > 0)
	{
		unsigned UTF32;
		// преобразуем в утф32 и "сдвигаемся" на следующий символ в строке
		textdraw = utf8_to_utf32(textdraw, &UTF32);
		// находим наш текущий символ
		eFontChar* DrawChar = vw_FindFontCharByUTF32(UTF32);
		if (DrawChar == 0) DrawChar = vw_LoadFontChar(UTF32);
		// первый символ - запоминаем его текстуру
		if (CurrentTexture == 0) CurrentTexture = DrawChar->CharTexture;


		// проверка на текстуру, если текстура поменялась - отрисовываем все что есть в буфере, если там что-то есть
		if (CurrentTexture != DrawChar->CharTexture)
		{
			// если что-то было в буфере - выводим
			if (k > 0)
			{
				// Установка текстуры
				vw_SetTexture(0, CurrentTexture);
				// отрисовываем все что есть в буфере
				vw_SendVertices(RI_QUADS, 4*(k/16), RI_2f_XY | RI_1_TEX, tmp, 4*sizeof(float));
			}


			// запоминаем новую текстуру
			CurrentTexture = DrawChar->CharTexture;
			// сбрасываем счетчики
			k=0;
		}


		// если не пробел - рисуем
		if (UTF32 != 0x020)
		{
			float DrawX = Xstart + DrawChar->Left;
			float DrawY = InternalFontSize - DrawChar->Top;


			float ImageHeight = DrawChar->CharTexture->Height*1.0f;
			float ImageWidth = DrawChar->CharTexture->Width*1.0f;

			float FrameHeight = (DrawChar->TexturePositionBottom*1.0f )/ImageHeight;
			float FrameWidth = (DrawChar->TexturePositionRight*1.0f )/ImageWidth;

			float Yst = (DrawChar->TexturePositionTop*1.0f)/ImageHeight;
			float Xst = (DrawChar->TexturePositionLeft*1.0f)/ImageWidth;

#ifdef USE_GLES
			tmp[k++] = DrawX/10.0f;
			tmp[k++] = (DrawY + DrawChar->Height)/10.0f;
			tmp[k++] = Xst;
			tmp[k++] = 1.0f-Yst;

			tmp[k++] = DrawX/10.0f;
			tmp[k++] = (DrawY + DrawChar->Height)/10.0f;
			tmp[k++] = Xst;
			tmp[k++] = 1.0f-Yst;

			tmp[k++] = DrawX/10.0f;
			tmp[k++] = DrawY/10.0f;
			tmp[k++] = Xst;
			tmp[k++] = 1.0f-FrameHeight;

			tmp[k++] = (DrawX + DrawChar->Width)/10.0f;
			tmp[k++] = (DrawY + DrawChar->Height)/10.0f;
			tmp[k++] = FrameWidth;
			tmp[k++] = 1.0f-Yst;

			tmp[k++] = (DrawX + DrawChar->Width)/10.0f;
			tmp[k++] = DrawY/10.0f;
			tmp[k++] = FrameWidth;
			tmp[k++] = 1.0f-FrameHeight;

			tmp[k++] = (DrawX + DrawChar->Width)/10.0f;
			tmp[k++] = DrawY/10.0f;
			tmp[k++] = FrameWidth;
			tmp[k++] = 1.0f-FrameHeight;
#else
			tmp[k++] = DrawX/10.0f;
			tmp[k++] = (DrawY + DrawChar->Height)/10.0f;
			tmp[k++] = Xst;
			tmp[k++] = 1.0f-Yst;

			tmp[k++] = DrawX/10.0f;
			tmp[k++] = DrawY/10.0f;
			tmp[k++] = Xst;
			tmp[k++] = 1.0f-FrameHeight;

			tmp[k++] = (DrawX + DrawChar->Width)/10.0f;
			tmp[k++] = DrawY/10.0f;
			tmp[k++] = FrameWidth;
			tmp[k++] = 1.0f-FrameHeight;

			tmp[k++] = (DrawX + DrawChar->Width)/10.0f;
			tmp[k++] = (DrawY + DrawChar->Height)/10.0f;
			tmp[k++] = FrameWidth;
			tmp[k++] = 1.0f-Yst;
#endif


			Xstart += DrawChar->AdvanceX;
		}
		else
		{
			Xstart += SpaceWidth;
		}

	}


	// если что-то было в буфере - выводим
	if (k > 0)
	{
		// Установка текстуры
		vw_SetTexture(0, CurrentTexture);
		// отрисовываем все что есть в буфере
#ifdef USE_GLES
		vw_SendVertices(RI_QUADS, 6*(k/16), RI_2f_XY | RI_1_TEX, tmp, 4*sizeof(float));
#else
		vw_SendVertices(RI_QUADS, 4*(k/16), RI_2f_XY | RI_1_TEX, tmp, 4*sizeof(float));
#endif
	}


	vw_PopMatrix();



	vw_SetTextureBlend(false, 0, 0);
	vw_BindTexture(0, 0);

}
//------------------------------------------------------------------------------------
// Прорисовка второго слоя "пыли" с тайловой анимацией
//------------------------------------------------------------------------------------
void StarSystemDrawSecondLayer(int DrawType)
{
	if (Setup.VisualEffectsQuality <= 1)
	{
		int VFV = RI_3f_XYZ | RI_4f_COLOR | RI_1_TEX;

		float *buff;
		buff = new float[4*9]; if (buff == 0) return;

		float width_2, heigh_2, length_2;
		width_2 = 0.0f;
		heigh_2 = 110.0f;
		length_2 = 110.0f;
		float x,y,z;
		x = GamePoint.x;
		y = GamePoint.y;
		z = GamePoint.z;
		float StartTransparentLayer2 = 0.9f;
		float EndTransparentLayer2 = 0.7f;

		if (DrawType == 2)
		{
			width_2 = length_2 = 175.0f;
			heigh_2 = 0.0f;

			VECTOR3D CurrentCameraLocation;
			vw_GetCameraLocation(&CurrentCameraLocation);

			x = GamePoint.x+GameCameraGetDeviation()*2.0f + CurrentCameraLocation.x*0.5f;
			y = GamePoint.y-GameCameraGetDeviation();
			z = GamePoint.z+25.0f;

			StartTransparentLayer2 = StarsTileStartTransparentLayer2;
			EndTransparentLayer2 = StarsTileEndTransparentLayer2;
		}


		int k=0;

		buff[k++] = x + width_2;
		buff[k++] = y + heigh_2;
		buff[k++] = z + length_2+length_2/2;
		buff[k++] = 1.0f;
		buff[k++] = 1.0f;
		buff[k++] = 1.0f;
		buff[k++] = StartTransparentLayer2;
		buff[k++] = 3.2f;
		buff[k++] = 0.0f+StarsTile2;

		buff[k++] = x + width_2;
		buff[k++] = y + heigh_2;
		buff[k++] = z - length_2/2;
		buff[k++] = 1.0f;
		buff[k++] = 1.0f;
		buff[k++] = 1.0f;
		buff[k++] = EndTransparentLayer2;
		buff[k++] = 3.2f;
		buff[k++] = 3.0f+StarsTile2;

		buff[k++] = x - width_2;
		buff[k++] = y - heigh_2;
		buff[k++] = z + length_2+length_2/2;
		buff[k++] = 1.0f;
		buff[k++] = 1.0f;
		buff[k++] = 1.0f;
		buff[k++] = StartTransparentLayer2;
		buff[k++] = 0.2f;
		buff[k++] = 0.0f+StarsTile2;

		buff[k++] = x - width_2;
		buff[k++] = y - heigh_2;
		buff[k++] = z - length_2/2;
		buff[k++] = 1.0f;
		buff[k++] = 1.0f;
		buff[k++] = 1.0f;
		buff[k++] = EndTransparentLayer2;
		buff[k++] = 0.2f;
		buff[k++] = 3.0f+StarsTile2;

		if (DrawType == 1)
		{
			StarsTile2 -= 0.04f*(vw_GetTime() - StarsTileUpdateTime2);
			StarsTileUpdateTime2 = vw_GetTime();
		}
		else
		{
			StarsTile2 -= 0.12f*(vw_GetTime(1) - StarsTileUpdateTime2);
			StarsTileUpdateTime2 = vw_GetTime(1);
		}
		if (StarsTile2 < -3.0f) StarsTile2 += 3.0f;


		eTexture *TileTexture = vw_FindTextureByName("DATA/SKYBOX/tile_stars.tga");
		vw_SetTexture(0, TileTexture);
		// по умолчанию всегда трилинейная фильтрация, если надо - ставим билинейную
		if (Setup.TextureFilteringMode == 1) vw_SetTextureFiltering(RI_TEXTURE_BILINEAR);


		vw_SetTextureBlend(true, RI_BLEND_SRCALPHA, RI_BLEND_ONE);

		vw_DepthTest(false, -1);

		if (DrawType == 1)
		{
			vw_PushMatrix();
			vw_Rotate(-20.0f, 0.0f, 0.0f, 1.0f);
			vw_Rotate(-45.0f, 0.0f, 1.0f, 0.0f);
			vw_Rotate(30.0f, 1.0f, 0.0f, 0.0f);
		}


		vw_SendVertices(RI_TRIANGLE_STRIP, 4, VFV, buff, 9*sizeof(float));

		if (DrawType == 1) vw_PopMatrix();

		vw_DepthTest(true, RI_LESSEQUAL);
		vw_SetTextureBlend(false, 0, 0);
		vw_BindTexture(0, 0);
		if (buff != 0){delete [] buff; buff = 0;}
	}
}
Ejemplo n.º 3
0
//-----------------------------------------------------------------------------
// прорисовка системы
//-----------------------------------------------------------------------------
void CSpaceStars::Draw()
{
	// загрузка текстуры, уже должна быть подключена
	if (Texture == 0) return;

	VECTOR3D CurrentCameraRotation;
	vw_GetCameraRotation(&CurrentCameraRotation);


	// если еще нет последовательности, или камеру повернули - надо пересчитать прорисовку
	if ((tmpDATA == 0 && VBO == 0) || CurrentCameraRotation.x != LastCameraAngleX || CurrentCameraRotation.y != LastCameraAngleY || CurrentCameraRotation.z != LastCameraAngleZ)
	{

		if (list != 0){delete [] list; list = 0;}
		if (tmpDATA != 0){delete [] tmpDATA; tmpDATA = 0;}
		if (VBO!=0){vw_DeleteVBO(*VBO); delete VBO; VBO=0;}

		// находим реальное кол-во частиц на прорисовку
		CStar *tmp = Start;
		PrimitCount = 0;

		// сохраняем данные
		LastCameraAngleX = CurrentCameraRotation.x;
		LastCameraAngleY = CurrentCameraRotation.y;
		LastCameraAngleZ = CurrentCameraRotation.z;

		// получаем текущее положение камеры
		VECTOR3D CurrentCameraLocation;
		vw_GetCameraLocation(&CurrentCameraLocation);


		while (tmp!=0)
		{
			CStar *tmp2 = tmp->Next;
			// небольшая оптимизация, если попадает в сферу - рисуем, нет - значит не видно
			if (vw_SphereInFrustum(tmp->Location + CurrentCameraLocation, Size))
				PrimitCount++;
			tmp = tmp2;
		}

		// если рисовать нечего - выходим
		if (PrimitCount == 0) return;

		// список, в котором они будут упорядочены
		list = new CStar*[PrimitCount]; if (list == 0) return;
		int LenCount = 0;
		float *Len = 0;

		tmp = Start;
		while (tmp!=0)
		{
			CStar *tmp2 = tmp->Next;
			// небольшая оптимизация, если попадает в сферу - рисуем, нет - значит не видно
			if (vw_SphereInFrustum(tmp->Location + CurrentCameraLocation, Size))
			{
				list[LenCount] = tmp;
				LenCount++;
			}
			tmp = tmp2;
		}



		// если не поддерживаем/не включены шейдеры, или нет поддержки вбо
		// делаем старым способом, через временный буфер
		if (!Setup.UseGLSL)
		{
			// делаем массив для всех элементов
#ifdef USE_GLES
			// войдет RI_3f_XYZ | RI_2f_TEX | RI_4ub_COLOR
			tmpDATA = new float[6*(3+2+1)*PrimitCount]; if (tmpDATA == 0) return;
#else
			// войдет RI_3f_XYZ | RI_2f_TEX | RI_4ub_COLOR
			tmpDATA = new float[4*(3+2+1)*PrimitCount]; if (tmpDATA == 0) return;
#endif
			GLubyte *tmpDATAub = (GLubyte *)tmpDATA;

			// номер float'а в последовательности
			int k=0;

			for (int i=0; i<PrimitCount; i++)
			{
				// находим вектор камера-точка
				VECTOR3D nnTmp;
				// смотрим, если есть не нужно поворачивать, работаем с направлением
				nnTmp = list[i]->Location^(-1.0f);
				nnTmp.Normalize();
				// находим перпендикуляр к вектору nnTmp
				VECTOR3D nnTmp2;
				nnTmp2.x = 1.0f;
				nnTmp2.y = 1.0f;
				nnTmp2.z = -(nnTmp.x + nnTmp.y)/nnTmp.z;
				nnTmp2.Normalize();
				// находим перпендикуляр к векторам nnTmp и nnTmp2
				// файтически - a x b = ( aybz - byaz , azbx - bzax , axby - bxay );
				VECTOR3D nnTmp3;
				nnTmp3.x = nnTmp.y*nnTmp2.z - nnTmp2.y*nnTmp.z;
				nnTmp3.y = nnTmp.z*nnTmp2.x - nnTmp2.z*nnTmp.x;
				nnTmp3.z = nnTmp.x*nnTmp2.y - nnTmp2.x*nnTmp.y;
				nnTmp3.Normalize();

				// находим
				VECTOR3D tmpAngle1,tmpAngle2,tmpAngle3,tmpAngle4;

				tmpAngle1 = nnTmp3^(Size*1.5f);
				tmpAngle3 = nnTmp3^(-Size*1.5f);
				tmpAngle2 = nnTmp2^(Size*1.5f);
				tmpAngle4 = nnTmp2^(-Size*1.5f);


				GLubyte A = (GLubyte)(list[i]->Alpha*255);

				// собираем четырехугольник

#ifdef USE_GLES
				tmpDATA[k++] = list[i]->Location.x+tmpAngle3.x;	// X
				tmpDATA[k++] = list[i]->Location.y+tmpAngle3.y;		// Y
				tmpDATA[k++] = list[i]->Location.z+tmpAngle3.z;		// Z
				tmpDATAub[k*sizeof(float)] = 204;
				tmpDATAub[k*sizeof(float)+1] = 204;
				tmpDATAub[k*sizeof(float)+2] = 255;
				tmpDATAub[k*sizeof(float)+3] = A;
				k++;
				tmpDATA[k++] = 0.0f;
				tmpDATA[k++] = 1.0f;

				tmpDATA[k++] = list[i]->Location.x+tmpAngle3.x;	// X
				tmpDATA[k++] = list[i]->Location.y+tmpAngle3.y;		// Y
				tmpDATA[k++] = list[i]->Location.z+tmpAngle3.z;		// Z
				tmpDATAub[k*sizeof(float)] = 204;
				tmpDATAub[k*sizeof(float)+1] = 204;
				tmpDATAub[k*sizeof(float)+2] = 255;
				tmpDATAub[k*sizeof(float)+3] = A;
				k++;
				tmpDATA[k++] = 0.0f;
				tmpDATA[k++] = 1.0f;

				tmpDATA[k++] = list[i]->Location.x+tmpAngle2.x;	// X
				tmpDATA[k++] = list[i]->Location.y+tmpAngle2.y;		// Y
				tmpDATA[k++] = list[i]->Location.z+tmpAngle2.z;		// Z
				tmpDATAub[k*sizeof(float)] = 204;
				tmpDATAub[k*sizeof(float)+1] = 204;
				tmpDATAub[k*sizeof(float)+2] = 255;
				tmpDATAub[k*sizeof(float)+3] = A;
				k++;
				tmpDATA[k++] = 0.0f;
				tmpDATA[k++] = 0.0f;

				tmpDATA[k++] = list[i]->Location.x+tmpAngle4.x;	// X
				tmpDATA[k++] = list[i]->Location.y+tmpAngle4.y;		// Y
				tmpDATA[k++] = list[i]->Location.z+tmpAngle4.z;		// Z
				tmpDATAub[k*sizeof(float)] = 204;
				tmpDATAub[k*sizeof(float)+1] = 204;
				tmpDATAub[k*sizeof(float)+2] = 255;
				tmpDATAub[k*sizeof(float)+3] = A;
				k++;
				tmpDATA[k++] = 1.0f;
				tmpDATA[k++] = 1.0f;

				tmpDATA[k++] = list[i]->Location.x+tmpAngle1.x;	// X
				tmpDATA[k++] = list[i]->Location.y+tmpAngle1.y;		// Y
				tmpDATA[k++] = list[i]->Location.z+tmpAngle1.z;		// Z
				tmpDATAub[k*sizeof(float)] = 204;
				tmpDATAub[k*sizeof(float)+1] = 204;
				tmpDATAub[k*sizeof(float)+2] = 255;
				tmpDATAub[k*sizeof(float)+3] = A;
				k++;
				tmpDATA[k++] = 1.0f;
				tmpDATA[k++] = 0.0f;

				tmpDATA[k++] = list[i]->Location.x+tmpAngle1.x;	// X
				tmpDATA[k++] = list[i]->Location.y+tmpAngle1.y;		// Y
				tmpDATA[k++] = list[i]->Location.z+tmpAngle1.z;		// Z
				tmpDATAub[k*sizeof(float)] = 204;
				tmpDATAub[k*sizeof(float)+1] = 204;
				tmpDATAub[k*sizeof(float)+2] = 255;
				tmpDATAub[k*sizeof(float)+3] = A;
				k++;
				tmpDATA[k++] = 1.0f;
				tmpDATA[k++] = 0.0f;
#else
				tmpDATA[k++] = list[i]->Location.x+tmpAngle3.x;	// X
				tmpDATA[k++] = list[i]->Location.y+tmpAngle3.y;		// Y
				tmpDATA[k++] = list[i]->Location.z+tmpAngle3.z;		// Z
				tmpDATAub[k*sizeof(float)] = 204;
				tmpDATAub[k*sizeof(float)+1] = 204;
				tmpDATAub[k*sizeof(float)+2] = 255;
				tmpDATAub[k*sizeof(float)+3] = A;
				k++;
				tmpDATA[k++] = 0.0f;
				tmpDATA[k++] = 1.0f;

				tmpDATA[k++] = list[i]->Location.x+tmpAngle2.x;	// X
				tmpDATA[k++] = list[i]->Location.y+tmpAngle2.y;		// Y
				tmpDATA[k++] = list[i]->Location.z+tmpAngle2.z;		// Z
				tmpDATAub[k*sizeof(float)] = 204;
				tmpDATAub[k*sizeof(float)+1] = 204;
				tmpDATAub[k*sizeof(float)+2] = 255;
				tmpDATAub[k*sizeof(float)+3] = A;
				k++;
				tmpDATA[k++] = 0.0f;
				tmpDATA[k++] = 0.0f;

				tmpDATA[k++] = list[i]->Location.x+tmpAngle1.x;	// X
				tmpDATA[k++] = list[i]->Location.y+tmpAngle1.y;		// Y
				tmpDATA[k++] = list[i]->Location.z+tmpAngle1.z;		// Z
				tmpDATAub[k*sizeof(float)] = 204;
				tmpDATAub[k*sizeof(float)+1] = 204;
				tmpDATAub[k*sizeof(float)+2] = 255;
				tmpDATAub[k*sizeof(float)+3] = A;
				k++;
				tmpDATA[k++] = 1.0f;
				tmpDATA[k++] = 0.0f;

				tmpDATA[k++] = list[i]->Location.x+tmpAngle4.x;	// X
				tmpDATA[k++] = list[i]->Location.y+tmpAngle4.y;		// Y
				tmpDATA[k++] = list[i]->Location.z+tmpAngle4.z;		// Z
				tmpDATAub[k*sizeof(float)] = 204;
				tmpDATAub[k*sizeof(float)+1] = 204;
				tmpDATAub[k*sizeof(float)+2] = 255;
				tmpDATAub[k*sizeof(float)+3] = A;
				k++;
				tmpDATA[k++] = 1.0f;
				tmpDATA[k++] = 1.0f;
#endif
			}
		}
		else
		{
			// все нормально, работаем с шейдерами и вбо


			// делаем массив для всех элементов
#ifdef USE_GLES
			// войдет RI_3f_XYZ | RI_2f_TEX | RI_3f_NORMAL*/
			tmpDATA = new float[6*(3+2+3)*PrimitCount]; if (tmpDATA == 0) return;
#else
			// войдет RI_3f_XYZ | RI_2f_TEX | RI_3f_NORMAL*/
			tmpDATA = new float[4*(3+2+3)*PrimitCount]; if (tmpDATA == 0) return;
#endif
			// номер float'а в последовательности
			int k=0;

			for (int i=0; i<PrimitCount; i++)
			{
				// находим вектор камера-точка
				VECTOR3D nnTmp;
				// смотрим, если есть не нужно поворачивать, работаем с направлением
				nnTmp = list[i]->Location^(-1.0f);
				nnTmp.Normalize();
				// находим перпендикуляр к вектору nnTmp
				VECTOR3D nnTmp2;
				nnTmp2.x = 1.0f;
				nnTmp2.y = 1.0f;
				nnTmp2.z = -(nnTmp.x + nnTmp.y)/nnTmp.z;
				nnTmp2.Normalize();
				// находим перпендикуляр к векторам nnTmp и nnTmp2
				// файтически - a x b = ( aybz - byaz , azbx - bzax , axby - bxay );
				VECTOR3D nnTmp3;
				nnTmp3.x = nnTmp.y*nnTmp2.z - nnTmp2.y*nnTmp.z;
				nnTmp3.y = nnTmp.z*nnTmp2.x - nnTmp2.z*nnTmp.x;
				nnTmp3.z = nnTmp.x*nnTmp2.y - nnTmp2.x*nnTmp.y;
				nnTmp3.Normalize();

				// находим
				VECTOR3D tmpAngle1,tmpAngle2,tmpAngle3,tmpAngle4;

				tmpAngle1 = nnTmp3^(Size*1.5f);
				tmpAngle3 = nnTmp3^(-Size*1.5f);
				tmpAngle2 = nnTmp2^(Size*1.5f);
				tmpAngle4 = nnTmp2^(-Size*1.5f);


				// собираем четырехугольник
				tmpDATA[k++] = list[i]->Location.x+tmpAngle3.x;	// X
				tmpDATA[k++] = list[i]->Location.y+tmpAngle3.y;		// Y
				tmpDATA[k++] = list[i]->Location.z+tmpAngle3.z;		// Z
				tmpDATA[k++] = 0.0f;// не задействован
				tmpDATA[k++] = 0.0f;// не задействован
				tmpDATA[k++] = list[i]->AlphaDelta;
				tmpDATA[k++] = 0.0f;
				tmpDATA[k++] = 1.0f;

				tmpDATA[k++] = list[i]->Location.x+tmpAngle2.x;	// X
				tmpDATA[k++] = list[i]->Location.y+tmpAngle2.y;		// Y
				tmpDATA[k++] = list[i]->Location.z+tmpAngle2.z;		// Z
				tmpDATA[k++] = 0.0f;// не задействован
				tmpDATA[k++] = 0.0f;// не задействован
				tmpDATA[k++] = list[i]->AlphaDelta;
				tmpDATA[k++] = 0.0f;
				tmpDATA[k++] = 0.0f;

				tmpDATA[k++] = list[i]->Location.x+tmpAngle1.x;	// X
				tmpDATA[k++] = list[i]->Location.y+tmpAngle1.y;		// Y
				tmpDATA[k++] = list[i]->Location.z+tmpAngle1.z;		// Z
				tmpDATA[k++] = 0.0f;// не задействован
				tmpDATA[k++] = 0.0f;// не задействован
				tmpDATA[k++] = list[i]->AlphaDelta;
				tmpDATA[k++] = 1.0f;
				tmpDATA[k++] = 0.0f;

				tmpDATA[k++] = list[i]->Location.x+tmpAngle4.x;	// X
				tmpDATA[k++] = list[i]->Location.y+tmpAngle4.y;		// Y
				tmpDATA[k++] = list[i]->Location.z+tmpAngle4.z;		// Z
				tmpDATA[k++] = 1.0f;// не задействован
				tmpDATA[k++] = 1.0f;// не задействован
				tmpDATA[k++] = list[i]->AlphaDelta;
				tmpDATA[k++] = 1.0f;
				tmpDATA[k++] = 1.0f;
			}

			if (CAPS->VBOSupported)
			{
				VBO = new unsigned int;
				if (!vw_BuildVBO(4*PrimitCount, tmpDATA, 8, VBO))
				{
					delete VBO; VBO = 0;
				}
				else
				{
					// только если поддерживае вбо, иначе им рисуем
					if (tmpDATA != 0){delete [] tmpDATA; tmpDATA = 0;}
				}
			}

			if (list != 0){delete [] list; list = 0;}
		}

		if (Len != 0){delete [] Len; Len = 0;}
	}





	if (PrimitCount > 0)
	{
		vw_SetTexture(0, Texture);
		vw_SetTextureBlend(true, RI_BLEND_SRCALPHA, RI_BLEND_ONE);


		// получаем текущее положение камеры
		VECTOR3D CurrentCameraLocation;
		vw_GetCameraLocation(&CurrentCameraLocation);
		CurrentCameraLocation += VECTOR3D(GameCameraGetDeviation()*0.9,-GameCameraGetDeviation()*0.5f,0.0f);


		vw_PushMatrix();
		vw_Translate(CurrentCameraLocation);



		if (!Setup.UseGLSL)
		{
#ifdef USE_GLES
			vw_SendVertices(RI_QUADS, 6*PrimitCount, RI_3f_XYZ | RI_4ub_COLOR | RI_1_TEX, tmpDATA, 6*sizeof(float));
#else
			vw_SendVertices(RI_QUADS, 4*PrimitCount, RI_3f_XYZ | RI_4ub_COLOR | RI_1_TEX, tmpDATA, 6*sizeof(float));
#endif
		}
		else
		{
			if (GLSL != 0)
			{
				vw_UseShaderProgram(GLSL);
				vw_Uniform1i(GLSL, UniformLocations[0], 0);
				vw_Uniform1f(GLSL, UniformLocations[1], Age);
			}

			vw_SendVertices(RI_QUADS, 4*PrimitCount, RI_3f_XYZ | RI_1_TEX | RI_3f_NORMAL, tmpDATA, 8*sizeof(float), VBO);

			if (GLSL != 0) vw_StopShaderProgram();
		}


		vw_PopMatrix();

		vw_SetTextureBlend(false, 0, 0);
	}





	vw_BindTexture(0, 0);
}
//------------------------------------------------------------------------------------
// StarSystem draw function
//------------------------------------------------------------------------------------
void StarSystemDraw(int DrawType)
{
	if (!StarSystem_InitedAll) return;

	// current camera location
	VECTOR3D CurrentCameraLocation;
	vw_GetCameraLocation(&CurrentCameraLocation);

	vw_DepthTest(false, -1);

	if (StarSystem_Inited)
	{
		// SkyBox
		vw_PushMatrix();
		vw_Translate(CurrentCameraLocation);
		vw_Rotate(StarSystem_BaseRotation.x, 1.0f, 0.0f, 0.0f);
		vw_Rotate(StarSystem_BaseRotation.y, 0.0f, 1.0f, 0.0f);
		vw_Rotate(StarSystem_BaseRotation.z, 0.0f, 0.0f, 1.0f);
		SkyBoxDraw();
		vw_PopMatrix();
	}

	// static space stars
	if (psSpaceStatic!=0) psSpaceStatic->Draw();

	vw_DepthTest(true, RI_LESSEQUAL);





	// космические объекты
	// рисуем планеты и большие астероиды _до_ тайловой анимации
	CSpaceObject *tmp1 = StartSpaceObject;
	while (tmp1!=0)
	{
		CSpaceObject *tmp2 = tmp1->Next;

		// если это планета на заднем фоне
		if (tmp1->ObjectType == 14)
		{
			if (DrawType == 2)
			{
				vw_PushMatrix();
				vw_Translate(VECTOR3D(CurrentCameraLocation.x*0.90f-GameCameraGetDeviation()*4.0f, GameCameraGetDeviation()*2.0f,0.0f));
			}
			tmp1->Draw(false);
			if (DrawType == 2) vw_PopMatrix();
		}
		else
		// если это большой астероид летящий на заднем фоне
		if (tmp1->ObjectType == 15 && (tmp1->ObjectCreationType>10 && tmp1->ObjectCreationType<20))
		{
			if (DrawType == 2)
			{
				vw_PushMatrix();
				vw_Translate(VECTOR3D(CurrentCameraLocation.x*0.70f-GameCameraGetDeviation()*4.0f, GameCameraGetDeviation()*2.0f,0.0f));
			}
			tmp1->Draw(false);
			if (DrawType == 2) vw_PopMatrix();
		}

		tmp1 = tmp2;
	}
	// очищаем буфер глубины, чтобы "3д подложка" не участвовала в проверке глубины
	vw_Clear(RI_DEPTH_BUFFER);


	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
	// Прорисовка подложки с тайловой анимацией
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
	{
		int VFV = RI_3f_XYZ | RI_4f_COLOR | RI_1_TEX;

		float *buff = 0;
		buff = new float[4*9]; if (buff == 0) return;

		float width_2, heigh_2, length_2;
		width_2 = 0.0f;
		heigh_2 = 110.0f;
		length_2 = 110.0f;
		float x,y,z;
		x = GamePoint.x;
		y = GamePoint.y;
		z = GamePoint.z;
		float StartTransparentLayer1 = 0.7f;
		float EndTransparentLayer1 = 0.7f;


		if (DrawType == 2)
		{
			width_2 = length_2 = 175.0f;
			heigh_2 = 0.0f;
			// чем ниже слой, тем меньше его двигаем при перемещении камеры (при стандартном аспект рейшен)
			x = GamePoint.x+GameCameraGetDeviation() + CurrentCameraLocation.x*0.8f;
			y = GamePoint.y-GameCameraGetDeviation()*0.5f;
			z = GamePoint.z+25.0f;

			StartTransparentLayer1 = StarsTileStartTransparentLayer1;
			EndTransparentLayer1 = StarsTileEndTransparentLayer1;
		}


		int k=0;

		buff[k++] = x + width_2;
		buff[k++] = y + heigh_2;
		buff[k++] = z + length_2+length_2/2;
		buff[k++] = 1.0f;
		buff[k++] = 1.0f;
		buff[k++] = 1.0f;
		buff[k++] = StartTransparentLayer1;
		buff[k++] = 1.0f;
		buff[k++] = 0.0f+StarsTile/3.0f;

		buff[k++] = x + width_2;
		buff[k++] = y + heigh_2;
		buff[k++] = z - length_2/2;
		buff[k++] = 1.0f;
		buff[k++] = 1.0f;
		buff[k++] = 1.0f;
		buff[k++] = EndTransparentLayer1;
		buff[k++] = 1.0f;
		buff[k++] = 1.0f+StarsTile/3.0f;

		buff[k++] = x - width_2;
		buff[k++] = y - heigh_2;
		buff[k++] = z + length_2+length_2/2;
		buff[k++] = 1.0f;
		buff[k++] = 1.0f;
		buff[k++] = 1.0f;
		buff[k++] = StartTransparentLayer1;
		buff[k++] = 0.0f;
		buff[k++] = 0.0f+StarsTile/3.0f;

		buff[k++] = x - width_2;
		buff[k++] = y - heigh_2;
		buff[k++] = z - length_2/2;
		buff[k++] = 1.0f;
		buff[k++] = 1.0f;
		buff[k++] = 1.0f;
		buff[k++] = EndTransparentLayer1;
		buff[k++] = 0.0f;
		buff[k++] = 1.0f+StarsTile/3.0f;


		if (DrawType == 1)
		{
			StarsTile -= 0.015f*(vw_GetTime() - StarsTileUpdateTime);
			StarsTileUpdateTime = vw_GetTime();
		}
		else
		{
			StarsTile -= 0.035f*(vw_GetTime(1) - StarsTileUpdateTime);
			StarsTileUpdateTime = vw_GetTime(1);
		}

		if (StarsTile < -3.0f) StarsTile += 3.0f;


		eTexture *TileTexture = vw_FindTextureByName("DATA/SKYBOX/tile_back.tga");
		vw_SetTexture(0, TileTexture);
		// по умолчанию всегда трилинейная фильтрация, если надо - ставим билинейную
		if (Setup.TextureFilteringMode == 1) vw_SetTextureFiltering(RI_TEXTURE_BILINEAR);

		vw_SetTextureBlend(true, RI_BLEND_SRCALPHA, RI_BLEND_ONE);

		vw_DepthTest(false, -1);

		if (DrawType == 1)
		{
			vw_PushMatrix();
			vw_Rotate(-20.0f, 0.0f, 0.0f, 1.0f);
			vw_Rotate(-45.0f, 0.0f, 1.0f, 0.0f);
			vw_Rotate(30.0f, 1.0f, 0.0f, 0.0f);
		}

		vw_SendVertices(RI_TRIANGLE_STRIP, 4, VFV, buff, 9*sizeof(float));



		// звезды рисуем отдельно, четкими (со своими текстурными координатами)

		k=0;

		buff[k++] = x + width_2;
		buff[k++] = y + heigh_2;
		buff[k++] = z + length_2+length_2/2;
		buff[k++] = 1.0f;
		buff[k++] = 1.0f;
		buff[k++] = 1.0f;
		buff[k++] = StartTransparentLayer1;
		buff[k++] = 3.0f;
		buff[k++] = 0.0f+StarsTile;

		buff[k++] = x + width_2;
		buff[k++] = y + heigh_2;
		buff[k++] = z - length_2/2;
		buff[k++] = 1.0f;
		buff[k++] = 1.0f;
		buff[k++] = 1.0f;
		buff[k++] = EndTransparentLayer1;
		buff[k++] = 3.0f;
		buff[k++] = 3.0f+StarsTile;

		buff[k++] = x - width_2;
		buff[k++] = y - heigh_2;
		buff[k++] = z + length_2+length_2/2;
		buff[k++] = 1.0f;
		buff[k++] = 1.0f;
		buff[k++] = 1.0f;
		buff[k++] = StartTransparentLayer1;
		buff[k++] = 0.0f;
		buff[k++] = 0.0f+StarsTile;

		buff[k++] = x - width_2;
		buff[k++] = y - heigh_2;
		buff[k++] = z - length_2/2;
		buff[k++] = 1.0f;
		buff[k++] = 1.0f;
		buff[k++] = 1.0f;
		buff[k++] = EndTransparentLayer1;
		buff[k++] = 0.0f;
		buff[k++] = 3.0f+StarsTile;

		vw_SetTexture(0, vw_FindTextureByName("DATA/SKYBOX/tile_stars.tga"));

		vw_SendVertices(RI_TRIANGLE_STRIP, 4, VFV, buff, 9*sizeof(float));




		if (DrawType == 1) vw_PopMatrix();

		vw_DepthTest(true, RI_LESSEQUAL);

		vw_SetTextureBlend(false, 0, 0);
		vw_BindTexture(0, 0);
		if (buff != 0){delete [] buff; buff = 0;}
	}



	// корректируем положение частиц "космической пыли", если в игре и камера движется
	if (DrawType == 2)
	{
		VECTOR3D TMPpsSpace;
		psSpace->GetLocation(&TMPpsSpace);
		psSpace->SetStartLocation(TMPpsSpace);
		psSpace->MoveSystemLocation(VECTOR3D(0,10,250)+GamePoint);
	}
}
Ejemplo n.º 5
0
//------------------------------------------------------------------------------------
// прорисовка фонта
//------------------------------------------------------------------------------------
void vw_DrawFont(int X, int Y, float FlattenWidth, float MaxWidth, float FontScale, float R, float G, float B, float Transp, const char *Text, ...)
{
	if (Text == 0) return;

	// учитываем аспект рейшен
	float AW;
	float AH;
	bool ASpresent=false;
	ASpresent = vw_GetAspectWH(&AW, &AH);
	// получаем данные текущего вьюпорта
	int W, H;
	vw_GetViewport(0, 0, &W, &H);
	float AHw = H*1.0f;

	float RealTextYPos = AHw - 2*Y + 4 + InternalFontSize*FontScale;
	if (ASpresent) RealTextYPos = AH - 2*Y + 4 + InternalFontSize*FontScale;


	// если текст ниже чем ширина нашего окна - не рисуем
	if (ASpresent){ if (Y > AH) return;}
	else {if (Y > H) return;}
	// если текст выше чем ноль - тоже рисовать его смысла нет
	if (Y+InternalFontSize*FontScale < 0) return;


// FlattenWidth - выравнивать по ширине
// если FlattenWidth отрицателен, выравниваем по значению, "сжимая" буквы, если нужно
// MaxWidth - рисовать до ширины


	// смотрим значения параметров в строке
	char	text[1024];
	va_list		ap;
	va_start(ap, Text);
	vsprintf(text, Text, ap);
	va_end(ap);
	// в text уже полная строка
	if (strlen(text) == 0) return;

	float Xstart = X;
	// сразу определяем "базовую" ширину пробела, чтобы учитывать в расчетах
	float SpaceWidth = vw_FindFontCharByUTF32(0x020)->AdvanceX*FontScale;
	// чтобы было более читаемо - делаем пробел не менее 2/3 ширины
	if (SpaceWidth < (InternalFontSize * 0.65f)) SpaceWidth = InternalFontSize * 0.65f;
	// коэф. изменения букв по ширине
	float FontWidthScale = 1.0f;

	if (Transp >= 1.0f) Transp = 1.0f;


	// если нужно выравнивать, считаем данные пробелов
	if (FlattenWidth > 0)
	{
		float LineWidth = 0;
		int SpaceCount = 0;

		const char *CountCheck = text;
		while (strlen(CountCheck) > 0)
		{
			unsigned UTF32;
			// преобразуем в утф32 и "сдвигаемся" на следующий символ в строке
			CountCheck = utf8_to_utf32(CountCheck, &UTF32);
			// находим наш текущий символ
			eFontChar* DrawChar = vw_FindFontCharByUTF32(UTF32);
			if (DrawChar == 0) DrawChar = vw_LoadFontChar(UTF32);

			// считаем кол-во пробелов
			if (UTF32 == 0x020)
				SpaceCount++;
			else
				LineWidth += DrawChar->AdvanceX;
		}

		if (FlattenWidth > LineWidth)
			if (SpaceCount!=0) SpaceWidth = (FlattenWidth - LineWidth)/SpaceCount;
	}
	// если нужно сжать, считаем коэф. сжатия букв
	if (FlattenWidth < 0)
	{
		float LineWidth = 0;

		const char *CountCheck = text;
		while (strlen(CountCheck) > 0)
		{
			unsigned UTF32;
			// преобразуем в утф32 и "сдвигаемся" на следующий символ в строке
			CountCheck = utf8_to_utf32(CountCheck, &UTF32);
			// находим наш текущий символ
			eFontChar* DrawChar = vw_FindFontCharByUTF32(UTF32);
			if (DrawChar == 0) DrawChar = vw_LoadFontChar(UTF32);

			// считаем длину символов с пробелами
			if (UTF32 != 0x020)
				LineWidth += DrawChar->AdvanceX;
			else
				LineWidth += SpaceWidth;
		}

		if (FlattenWidth*(-1.0f) < LineWidth) FontWidthScale = FlattenWidth/LineWidth*(-1.0f);
	}


	float LineWidth = 0;

	// установка свойств текстуры
	vw_SetTextureBlend(true, RI_BLEND_SRCALPHA, RI_BLEND_INVSRCALPHA);
	// ставим цвет
	vw_SetColor(R, G, B, Transp);

	// для отрисовки
	eTexture* CurrentTexture = 0;
	int k=0;
	// буфер для последовательности RI_QUADS
	// войдет RI_2f_XYZ | RI_2f_TEX
#ifdef USE_GLES
	GLshort *tmp = 0;
	tmp = new GLshort[(2+2)*6*strlen(text)]; if (tmp == 0) return;
#else
	float *tmp = 0;
	tmp = new float[(2+2)*4*strlen(text)]; if (tmp == 0) return;
#endif

	// чтобы меньше делать операций умножения, включаем коэф. один в другой сразу для ширины символов
	FontWidthScale = FontScale*FontWidthScale;


	// прорисовка текста
	const char *textdraw = text;
	// прорисовываем все символы
	while (strlen(textdraw) > 0)
	{
		unsigned UTF32;
		// преобразуем в утф32 и "сдвигаемся" на следующий символ в строке
		textdraw = utf8_to_utf32(textdraw, &UTF32);
		// находим наш текущий символ
		eFontChar* DrawChar = vw_FindFontCharByUTF32(UTF32);
		if (DrawChar == 0) DrawChar = vw_LoadFontChar(UTF32);
		// первый символ - запоминаем его текстуру
		if (CurrentTexture == 0) CurrentTexture = DrawChar->CharTexture;


		// проверка на текстуру, если текстура поменялась - отрисовываем все что есть в буфере, если там что-то есть
		if (CurrentTexture != DrawChar->CharTexture)
		{
			// если что-то было в буфере - выводим
			if (k > 0)
			{
				// Установка текстуры
				vw_SetTexture(0, CurrentTexture);
				// отрисовываем все что есть в буфере
#ifdef USE_GLES
				vw_MatrixMode(RI_TEXTURE_MATRIX);
				vw_LoadIdentity();
				vw_Scale(1.0f/CurrentTexture->Width,1.0f/CurrentTexture->Height,1.0f);
				vw_PushMatrix();
				vw_MatrixMode(RI_MODELVIEW_MATRIX);
				vw_SendVertices(RI_TRIANGLES, 6*(k/24), RI_2s_XY | RI_2s_TEX | RI_1_TEX, tmp, 4*sizeof(GLshort));
				vw_PopMatrix();
				vw_MatrixMode(RI_TEXTURE_MATRIX);
				vw_LoadIdentity();
#else
				vw_SendVertices(RI_QUADS, 4*(k/16), RI_2f_XY | RI_1_TEX, tmp, 4*sizeof(float));
#endif
			}


			// запоминаем новую текстуру
			CurrentTexture = DrawChar->CharTexture;
			// сбрасываем счетчики
			k=0;
		}

#ifdef USE_GLES
		float DrawX = (Xstart + DrawChar->Left*FontWidthScale);
		float DrawY = (Y + 2 + (InternalFontSize - DrawChar->Top)*FontScale); // 2 доп смещение ("привет" от старого фонта)
		
		// Вычисление поправки по У в зависимости от DrawCorner
		// - расположения угла начала координат
		float tmpPosY = 0;
		// изменяем только в случае RI_UL_CORNER
		if (ASpresent) tmpPosY = (AH - DrawY - DrawY - DrawChar->Height*FontScale);
		else tmpPosY = (AHw - DrawY - DrawY - DrawChar->Height*FontScale);

		// если не пробел - рисуем
		if (UTF32 != 0x020)
		{

			GLshort ImageHeight = DrawChar->CharTexture->Height;
			GLshort ImageWidth = DrawChar->CharTexture->Width;

			GLshort FrameHeight = (DrawChar->TexturePositionBottom);
			GLshort FrameWidth = (DrawChar->TexturePositionRight);

			GLshort Yst = (DrawChar->TexturePositionTop);
			GLshort Xst = (DrawChar->TexturePositionLeft);


			tmp[k++] = (GLshort)DrawX;
			tmp[k++] = (GLshort)(DrawY + tmpPosY + DrawChar->Height*FontScale);
			tmp[k++] = Xst;
			tmp[k++] = ImageHeight-Yst;

			tmp[k++] = (GLshort)DrawX;
			tmp[k++] = (GLshort)(DrawY + tmpPosY);
			tmp[k++] = Xst;
			tmp[k++] = ImageHeight-FrameHeight;

			tmp[k++] = (GLshort)(DrawX + DrawChar->Width*FontWidthScale);
			tmp[k++] = (GLshort)(DrawY + tmpPosY + DrawChar->Height*FontScale);
			tmp[k++] = FrameWidth;
			tmp[k++] = ImageHeight-Yst;


			tmp[k++] = (GLshort)DrawX;
			tmp[k++] = (GLshort)(DrawY + tmpPosY);
			tmp[k++] = Xst;
			tmp[k++] = ImageHeight-FrameHeight;

			tmp[k++] = (GLshort)(DrawX + DrawChar->Width*FontWidthScale);
			tmp[k++] = (GLshort)(DrawY + tmpPosY);
			tmp[k++] = FrameWidth;
			tmp[k++] = ImageHeight-FrameHeight;


			tmp[k++] = (GLshort)(DrawX + DrawChar->Width*FontWidthScale);
			tmp[k++] = (GLshort)(DrawY + tmpPosY + DrawChar->Height*FontScale);
			tmp[k++] = FrameWidth;
			tmp[k++] = ImageHeight-Yst;
			Xstart += (DrawChar->Width + DrawChar->Left)*FontWidthScale;
			LineWidth += (DrawChar->Width + DrawChar->Left)*FontWidthScale;
		}
		else
		{
			Xstart += SpaceWidth*FontWidthScale;
			LineWidth += SpaceWidth*FontWidthScale;
		}
#else
		// если не пробел - рисуем
		if (UTF32 != 0x020)
		{

			float DrawX = Xstart + DrawChar->Left*FontWidthScale;
			float DrawY = Y + GlobalFontOffsetY + (InternalFontSize - DrawChar->Top)*FontScale;

			// Вычисление поправки по У в зависимости от DrawCorner
			// - расположения угла начала координат
			float tmpPosY = 0;
			// изменяем только в случае RI_UL_CORNER
			if (ASpresent) tmpPosY = (AH - DrawY - DrawY - DrawChar->Height*FontScale);
			else tmpPosY = (AHw - DrawY - DrawY - DrawChar->Height*FontScale);

			float ImageHeight = DrawChar->CharTexture->Height*1.0f;
			float ImageWidth = DrawChar->CharTexture->Width*1.0f;

			float FrameHeight = (DrawChar->TexturePositionBottom*1.0f )/ImageHeight;
			float FrameWidth = (DrawChar->TexturePositionRight*1.0f )/ImageWidth;

			float Yst = (DrawChar->TexturePositionTop*1.0f)/ImageHeight;
			float Xst = (DrawChar->TexturePositionLeft*1.0f)/ImageWidth;

			tmp[k++] = DrawX;
			tmp[k++] = DrawY +tmpPosY + DrawChar->Height*FontScale;
			tmp[k++] = Xst;
			tmp[k++] = 1.0f-Yst;

			tmp[k++] = DrawX;
			tmp[k++] = DrawY +tmpPosY;
			tmp[k++] = Xst;
			tmp[k++] = 1.0f-FrameHeight;

			tmp[k++] = DrawX + DrawChar->Width*FontWidthScale;
			tmp[k++] = DrawY +tmpPosY;
			tmp[k++] = FrameWidth;
			tmp[k++] = 1.0f-FrameHeight;

			tmp[k++] = DrawX + DrawChar->Width*FontWidthScale;
			tmp[k++] = DrawY +tmpPosY + DrawChar->Height*FontScale;
			tmp[k++] = FrameWidth;
			tmp[k++] = 1.0f-Yst;


			Xstart += DrawChar->AdvanceX*FontWidthScale;
			LineWidth += DrawChar->AdvanceX*FontWidthScale;
		}
		else
		{
			Xstart += SpaceWidth*FontWidthScale;
			LineWidth += SpaceWidth*FontWidthScale;
		}
#endif
		// если нужно прорисовывать с ограничением по длине
		if (MaxWidth != 0.0f)
			if (LineWidth >= MaxWidth) break;
	}


	// если что-то было в буфере - выводим
	if (k > 0)
	{
		// Установка текстуры
		vw_SetTexture(0, CurrentTexture);
		// отрисовываем все что есть в буфере
#ifdef USE_GLES
		vw_MatrixMode(RI_TEXTURE_MATRIX);
		vw_LoadIdentity();
		vw_Scale(1.0f/CurrentTexture->Width,1.0f/CurrentTexture->Height,1.0f);
		vw_MatrixMode(RI_MODELVIEW_MATRIX);
		vw_PushMatrix();
		vw_SendVertices(RI_TRIANGLES, 6*(k/24), RI_2s_XY | RI_2s_TEX | RI_1_TEX, tmp, 4*sizeof(GLshort));
		vw_PopMatrix();
		vw_MatrixMode(RI_TEXTURE_MATRIX);
		vw_LoadIdentity();
#else
		vw_SendVertices(RI_QUADS, 4*(k/16), RI_2f_XY | RI_1_TEX, tmp, 4*sizeof(float));
#endif
	}



	if (tmp != 0){delete [] tmp; tmp = 0;}
	vw_SetColor(1.0f, 1.0f, 1.0f, 1.0f);
	vw_SetTextureBlend(false, 0, 0);
	vw_BindTexture(0, 0);
}