//----------------------------------------------------------------------------- // установка камеры //----------------------------------------------------------------------------- void vw_CameraLookAt(void) { // установка камеры vw_Rotate(-CameraRotation.x, 1.0f, 0.0f, 0.0f); vw_Rotate(-CameraRotation.y, 0.0f, 1.0f, 0.0f); vw_Rotate(-CameraRotation.z, 0.0f, 0.0f, 1.0f); vw_Translate((CameraLocation^(-1.0f))-CameraDeviation); // получаем фруструм if (CameraUpdated) { vw_CalculateFrustum(); CameraUpdated = false; } }
//------------------------------------------------------------------------------------ // прорисовка фонта в 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;} } }
//------------------------------------------------------------------------------------ // 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); } }