//----------------------------------------------------------------------------- // установка камеры //----------------------------------------------------------------------------- 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); }
//------------------------------------------------------------------------------------ // 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); } }
//----------------------------------------------------------------------------- // прорисовка системы //----------------------------------------------------------------------------- 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); }