/****************************************************************************** This source file is part of AstroMenace game (Hardcore 3D space shooter with spaceship upgrade possibilities.) For the latest info, see http://www.viewizard.com/ File name: SpaceExplosion.cpp Copyright (c) 2006-2007 Michael Kurinnoy, Viewizard All Rights Reserved. File Version: 1.2 ****************************************************************************** AstroMenace game source code available under "dual licensing" model. The licensing options available are: * Commercial Licensing. This is the appropriate option if you are creating proprietary applications and you are not prepared to distribute and share the source code of your application. Contact us for pricing at viewizard@viewizard.com * Open Source Licensing. This is the appropriate option if you want to share the source code of your application with everyone you distribute it to, and you also want to give them the right to share who uses it. You should have received a copy of the GNU General Public License version 3 with this source codes. If not, see . ******************************************************************************/ /// подключаем нужные файлы #include "SpaceExplosion.h" #include "../../../Game.h" //----------------------------------------------------------------------------- // Создание взрыва из частей объекта //----------------------------------------------------------------------------- void CSpaceExplosion::Create(CObject3D *Object, int ExplType, VECTOR3D ExplLocation, float Speed, int ObjectPieceNum, bool NeedExplosionSFX) { // если ObjectPieceNum==-1 полный взрыв... не частями // например ядерная ракета взрывает все объекты, или это астероид TimeLastUpdate = Object->TimeLastUpdate; ExplosionTypeByClass = 1; // 1-взрыв на части, 2-разлет геометрии int InternalExplosionType = 0; // общий - пенальти, если не игрок float CurrentPenalty = GameNPCWeaponPenalty*1.0f+1.0f; // чуть больше убираем... // если игрок или свои - ничего не надо... if (Object != 0) if (Object->ObjectStatus >= 2) CurrentPenalty = 1.0f; // сохраняем статус объекта, чтобы правильно создавать части-снаряды и обломки if (Object != 0) ObjectStatus = Object->ObjectStatus; // сохраняем тип взрыва ExplosionType = ExplType; // для регулирования ускорения разлета геометрии float MeshAcc = 0.0f; //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // малый внутренний взрыв для астероидов //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ if (ExplType == 1) { InternalExplosionType = 2; OldSpeed = Speed; Lifetime = 2.0f; // должно соотв. максимальной жизни частицы MeshAcc = 10.0f; // сохраняем данные объекта, чтобы не было скачков и не учитывать смещение в меше SetLocation(Object->Location); Orientation = Object->Orientation; // эффект GraphicFXQuantity = 1; GraphicFX = new eParticleSystem*[GraphicFXQuantity]; for (int i=0; iRadius/2.0f; GraphicFX[0] = new eParticleSystem; SetExplosionGFX(GraphicFX[0], 1); GraphicFX[0]->Speed = 1.5f*Object->Radius; GraphicFX[0]->SpeedVar = vw_Randf0; GraphicFX[0]->MoveSystem(Object->Location); GraphicFX[0]->ParticlesPerSec = (int)(10*Object->Radius); GraphicFX[0]->Direction = Object->Orientation; GraphicFX[0]->CreationType = 2; GraphicFX[0]->CreationSize = VECTOR3D(tRadius,tRadius,tRadius); GraphicFX[0]->Life = 1.5f; GraphicFX[0]->SizeStart = tRadius/1.5f; // создаем немного разлетающихся кусков-снарядов int ttt = (int)(3*Object->Radius) + (int)(vw_Randf0*3*Object->Radius); for (int i=0; iCreate(1); Projectile->SetLocation(Location); Projectile->SetRotation(VECTOR3D(360.0f*vw_Randf0, 360.0f*vw_Randf0, 360.0f*vw_Randf0)); VECTOR3D TM1 = Object->Orientation^Speed; Projectile->Orientation = TM1 + Projectile->Orientation^(Object->Radius*6.0f); Projectile->Orientation.Normalize(); for (int i=0; iGraphicFXQuantity; i++) { Projectile->GraphicFX[i]->Direction = Projectile->Orientation^-1; Projectile->GraphicFX[i]->Speed = 1.5f; } Projectile->ObjectStatus = ObjectStatus; // учитываем пенальти Projectile->Speed = Speed + Object->Radius*2.0f + 2.0f*vw_Randf0; Projectile->SpeedEnd = 0.0f; Projectile->SpeedStart = Projectile->Speed; Projectile->Lifetime = Projectile->Age = 1.0f+vw_Randf0; Projectile->DamageHull = Projectile->DamageHull/CurrentPenalty; Projectile->DamageSystems = Projectile->DamageSystems/CurrentPenalty; } } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // средний внутренний взрыв для пришельцев //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ if (ExplType == 2) { InternalExplosionType = 2; OldSpeed = Speed; Lifetime = 3.0f; // должно соотв. максимальной жизни частицы MeshAcc = 20.0f; // сохраняем данные объекта, чтобы не было скачков и не учитывать смещение в меше SetLocation(Object->Location); Orientation = Object->Orientation; // эффект GraphicFXQuantity = 3; GraphicFX = new eParticleSystem*[GraphicFXQuantity]; for (int i=0; iMoveSystem(Object->Location); GraphicFX[1]->ParticlesPerSec = (int)(2.5f*Object->Radius); GraphicFX[1]->Direction = Object->Orientation; GraphicFX[1]->CreationSize = VECTOR3D(Object->Radius/4,Object->Radius/4,Object->Radius/4); GraphicFX[2] = new eParticleSystem; SetExplosionGFX(GraphicFX[2], 4); GraphicFX[2]->Speed = Object->Radius/3.0f; GraphicFX[2]->SpeedVar = 1.0f*vw_Randf0; GraphicFX[2]->MoveSystem(Object->Location); if (Speed!=0) GraphicFX[2]->Theta = 360.00f/(Speed/8); GraphicFX[2]->ParticlesPerSec = (int)(2.5*Object->Radius); GraphicFX[2]->Direction = Object->Orientation; GraphicFX[2]->NeedStop = false; GraphicFX[0] = new eParticleSystem; SetExplosionGFX(GraphicFX[0], 2); GraphicFX[0]->Speed = Object->Radius*1.2f; GraphicFX[0]->SpeedVar = 1.0f*vw_Randf0; GraphicFX[0]->MoveSystem(Object->Location); if (Speed!=0) GraphicFX[0]->Theta = 360.00f/(Speed/8); GraphicFX[0]->ParticlesPerSec = (int)(10*Object->Radius); GraphicFX[0]->Direction = Object->Orientation; // создаем немного разлетающихся кусков-снарядов int ttt = (int)(Object->Radius) + (int)(vw_Randf0*Object->Radius); for (int i=0; iCreate(1); Projectile->SetLocation(Location); Projectile->SetRotation(VECTOR3D(360.0f*vw_Randf0, 360.0f*vw_Randf0, 360.0f*vw_Randf0)); VECTOR3D TM1 = Object->Orientation^Speed; Projectile->Orientation = TM1 + (Projectile->Orientation^(Object->Radius/4.0f)); Projectile->Orientation.Normalize(); for (int i=0; iGraphicFXQuantity; i++) { Projectile->GraphicFX[i]->Direction = Projectile->Orientation^-1; Projectile->GraphicFX[i]->Speed = 2.5f; Projectile->GraphicFX[i]->ColorStart.r = 0.30f; Projectile->GraphicFX[i]->ColorStart.g = 1.00f; Projectile->GraphicFX[i]->ColorStart.b = 1.00f; Projectile->GraphicFX[i]->ColorEnd.r = 0.00f; Projectile->GraphicFX[i]->ColorEnd.g = 1.00f; Projectile->GraphicFX[i]->ColorEnd.b = 1.00f; } Projectile->ObjectStatus = ObjectStatus; // учитываем пенальти Projectile->Speed = Speed + Object->Radius/2.0f + 2.0f*vw_Randf0; Projectile->SpeedEnd = 0.0f; Projectile->SpeedStart = Projectile->Speed; Projectile->Lifetime = Projectile->Age = 1.5f+vw_Randf0; Projectile->DamageHull = Projectile->DamageHull/CurrentPenalty; Projectile->DamageSystems = Projectile->DamageSystems/CurrentPenalty; } } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // средний внутренний взрыв для больших пиратов c разлетем частей // + именно так взрываем свои корабли и корабль игрока... //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ if (ExplType == 31) { InternalExplosionType = 1; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // взрыв внутренний части (пираты, земляне) //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ if (ExplType == 32) { InternalExplosionType = 2; OldSpeed = Speed; Lifetime = 3.0f; // должно соотв. максимальной жизни частицы MeshAcc = 20.0f; // сохраняем данные объекта, чтобы не было скачков и не учитывать смещение в меше SetLocation(Object->Location); Orientation = Object->Orientation; // эффект GraphicFXQuantity = 2; GraphicFX = new eParticleSystem*[GraphicFXQuantity]; for (int i=0; iSpeed = Object->Radius/1.4f; GraphicFX[1]->SpeedVar = 1.0f*vw_Randf0; GraphicFX[1]->MoveSystem(Object->Location); if (Speed>0.01f) GraphicFX[1]->Theta = 360.00f/(Speed/8); GraphicFX[1]->ParticlesPerSec = (int)(7*Object->Radius); GraphicFX[1]->Direction = Object->Orientation; GraphicFX[0] = new eParticleSystem; SetExplosionGFX(GraphicFX[0], 5); GraphicFX[0]->Speed = Object->Radius*1.1f; GraphicFX[0]->SpeedVar = 1.0f*vw_Randf0; GraphicFX[0]->MoveSystem(Object->Location); if (Speed>0.01f) GraphicFX[0]->Theta = 360.00f/(Speed/8); GraphicFX[0]->ParticlesPerSec = (int)(7*Object->Radius); GraphicFX[0]->Direction = Object->Orientation; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // взрыв на части (босс пришельцев) //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ if (ExplType == 33) { InternalExplosionType = 1; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // взрыв внутренний части (босс пришельцев) //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ if (ExplType == 34) { InternalExplosionType = 2; OldSpeed = Speed; Lifetime = 3.0f; // должно соотв. максимальной жизни частицы MeshAcc = 20.0f; // сохраняем данные объекта, чтобы не было скачков и не учитывать смещение в меше SetLocation(Object->Location); Orientation = Object->Orientation; // эффект GraphicFXQuantity = 2; GraphicFX = new eParticleSystem*[GraphicFXQuantity]; for (int i=0; iSpeed = Object->Radius/1.4f; GraphicFX[1]->SpeedVar = 1.0f*vw_Randf0; GraphicFX[1]->MoveSystem(Object->Location); if (Speed!=0) GraphicFX[1]->Theta = 360.00f/(Speed/8); GraphicFX[1]->ParticlesPerSec = (int)(7*Object->Radius); GraphicFX[1]->Direction = Object->Orientation; GraphicFX[0] = new eParticleSystem; SetExplosionGFX(GraphicFX[0], 11); GraphicFX[0]->Speed = Object->Radius*1.1f; GraphicFX[0]->SpeedVar = 1.0f*vw_Randf0; GraphicFX[0]->MoveSystem(Object->Location); if (Speed!=0) GraphicFX[0]->Theta = 360.00f/(Speed/8); GraphicFX[0]->ParticlesPerSec = (int)(7*Object->Radius); GraphicFX[0]->Direction = Object->Orientation; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // средний внутренний взрыв для землян и пиратов //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ if (ExplType == 3) { InternalExplosionType = 2; OldSpeed = Speed; Lifetime = 3.0f; // должно соотв. максимальной жизни частицы MeshAcc = 20.0f; // сохраняем данные объекта, чтобы не было скачков и не учитывать смещение в меше SetLocation(Object->Location); Orientation = Object->Orientation; // эффект GraphicFXQuantity = 2; GraphicFX = new eParticleSystem*[GraphicFXQuantity]; for (int i=0; iSpeed = Object->Radius/1.3f; GraphicFX[1]->SpeedVar = 1.0f*vw_Randf0; GraphicFX[1]->MoveSystem(Object->Location); if (Speed!=0) GraphicFX[1]->Theta = 360.00f/(Speed/8); GraphicFX[1]->ParticlesPerSec = (int)(7*Object->Radius); GraphicFX[1]->Direction = Object->Orientation; GraphicFX[0] = new eParticleSystem; SetExplosionGFX(GraphicFX[0], 5); GraphicFX[0]->Speed = Object->Radius*1.1f; GraphicFX[0]->SpeedVar = 1.0f*vw_Randf0; GraphicFX[0]->MoveSystem(Object->Location); if (Speed!=0) GraphicFX[0]->Theta = 360.00f/(Speed/8); GraphicFX[0]->ParticlesPerSec = (int)(7*Object->Radius); GraphicFX[0]->Direction = Object->Orientation; // создаем немного разлетающихся кусков-снарядов int ttt = (int)(0.5f*Object->Radius) + (int)(vw_Randf0*Object->Radius); for (int i=0; iCreate(1); Projectile->SetLocation(Location); Projectile->SetRotation(VECTOR3D(360.0f*vw_Randf0, 360.0f*vw_Randf0, 360.0f*vw_Randf0)); VECTOR3D TM1 = Object->Orientation^Speed; Projectile->Orientation = TM1 + (Projectile->Orientation^(Object->Radius/2.0f)); Projectile->Orientation.Normalize(); for (int i=0; iGraphicFXQuantity; i++) { Projectile->GraphicFX[i]->Direction = Projectile->Orientation^-1; Projectile->GraphicFX[i]->Speed = 2.5f; } Projectile->ObjectStatus = ObjectStatus; // учитываем пенальти Projectile->Speed = Speed + Object->Radius/2.0f + 2.0f*vw_Randf0; Projectile->SpeedEnd = 0.0f; Projectile->SpeedStart = Projectile->Speed; Projectile->Lifetime = Projectile->Age = 1.5f+vw_Randf0; Projectile->DamageHull = Projectile->DamageHull/CurrentPenalty; Projectile->DamageSystems = Projectile->DamageSystems/CurrentPenalty; } } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // распад ракеты, если она папала в облако фларес //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ if (ExplType == 4) { InternalExplosionType = 2; // резко тормозим OldSpeed = Speed/5.0f; Lifetime = 1.0f; // должно соотв. максимальной жизни частицы MeshAcc = 5.0f; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // взрыв на части для больших кораблей //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ if (InternalExplosionType == 1) { // строим обратную матрицу float InvRotationMat[9]; // сохраняем старые значения + пересчет новых memcpy(InvRotationMat, Object->CurrentRotationMat, 9*sizeof(float)); // делаем инверсную старую матрицу Matrix33InverseRotate(InvRotationMat); // содаем части, отделяем их от общей модели // ставим свои ориентейшины и скорость for (int i=0; iDrawObjectQuantity; i++) { // могут быть пустые группы, убираем их и идем смотрим на следующую группу if (Object->DrawObjectList[i].VertexCount == 0) continue; CShipPart *ShipPart; ShipPart = new CShipPart; ShipPart->ObjectType = 8; ShipPart->ShowDeleteOnHide = 0; // только одна текстура (!) 2-ю для подстветки не тянем ShipPart->Texture = new eTexture*[1]; ShipPart->Texture[0] = Object->Texture[i]; // берем то, что нужно ShipPart->DrawObjectQuantity = 1; ShipPart->DrawObjectList = new eObjectBlock[ShipPart->DrawObjectQuantity]; // копируем данные (тут уже все есть, с указателями на вбо и массив геометрии) memcpy(&(ShipPart->DrawObjectList[0]), &(Object->DrawObjectList[i]), sizeof(eObjectBlock)); // если надо было удалить в объекте - ставим не удалять, удалим вместе с этой частью Object->DrawObjectList[i].VertexBufferDestrType = 0; // резервируем память для HitBB ShipPart->HitBBLocation = new VECTOR3D[ShipPart->DrawObjectQuantity]; ShipPart->HitBBRadius2 = new float[ShipPart->DrawObjectQuantity]; ShipPart->HitBBSize = new VECTOR3D[ShipPart->DrawObjectQuantity]; ShipPart->HitBB = new VECTOR3D*[ShipPart->DrawObjectQuantity]; for (int i1=0; i1DrawObjectQuantity; i1++) { ShipPart->HitBB[i1] = new VECTOR3D[8]; } // находим точку локального положения объекта в моделе VECTOR3D LocalLocation = Object->DrawObjectList[i].Location; Matrix33CalcPoint(&LocalLocation, Object->CurrentRotationMat); LocalLocation += Object->HitBBLocation[i]; VECTOR3D LocalLocationTmp = Object->HitBBLocation[i]; Matrix33CalcPoint(&LocalLocationTmp, InvRotationMat); // и меняем внутрее положение ShipPart->DrawObjectList[0].Location = LocalLocationTmp^(-1.0f); // находим все данные по геометрии ShipPart->InitByDrawObjectList(); // установка текущего положения и поворота ShipPart->SetLocation(Object->Location+LocalLocation); ShipPart->SetRotation(Object->Rotation); ShipPart->Speed = Speed-2*vw_Randf1; ShipPart->RotationSpeed.x = 2.0f*vw_Randf0; ShipPart->RotationSpeed.y = 2.0f*vw_Randf0; ShipPart->StrengthStart = ShipPart->Strength = 1.0f; ShipPart->ObjectStatus = Object->ObjectStatus; ShipPart->ShowStrength = false; // взрываем тот объект, в который попали int NeedExplosionType = 32; switch (ExplType) { case 31: // взрыв пиратов или землян NeedExplosionType = 32; break; case 33: // взрыв боссов пришельцев // взорвем все в течении 3-х секунд ShipPart->BossPartCountDown = 3.0f * vw_Randf1; NeedExplosionType = 34; break; } if (ObjectPieceNum != -1) if (ObjectPieceNum == i) { CSpaceExplosion *TMPExplosion; TMPExplosion = new CSpaceExplosion; TMPExplosion->Create(ShipPart, NeedExplosionType, ShipPart->Location, ShipPart->Speed, -1); if (ShipPart != 0){delete ShipPart; ShipPart = 0;} } } Lifetime = 0.0f; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // взрыв с разлетом геометрии //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ if (InternalExplosionType == 2) { // AABB нужен, т.к. по нему рисуем, если во фруструме // копируем AABB, т.к. они сейчас подходят... AABB[0] = Object->AABB[0]; AABB[1] = Object->AABB[1]; AABB[2] = Object->AABB[2]; AABB[3] = Object->AABB[3]; AABB[4] = Object->AABB[4]; AABB[5] = Object->AABB[5]; AABB[6] = Object->AABB[6]; AABB[7] = Object->AABB[7]; // поправка в зависимости от скорости объекта до взрыва VelocityOrientation = Object->Orientation; // общее кол-во элементов прорисовки (т.к. может быть не один объект + разные настройки качества взрыва) int TotalCount = 0; // создаем последовательность DrawObjectQuantity = Object->DrawObjectQuantity; Texture = new eTexture*[DrawObjectQuantity]; DrawObjectList = new eObjectBlock[DrawObjectQuantity]; // смотрим по настройкам сколько пропускать int NeedIn = Setup.PartsExplosionQuality; // составляем данные для взрыва for (int i=0; iTexture[i]; // копируем данные memcpy(&(DrawObjectList[i]), &(Object->DrawObjectList[i]), sizeof(eObjectBlock)); // делаем изменения DrawObjectList[i].VertexBufferVBO = 0; DrawObjectList[i].VertexBuffer = 0; DrawObjectList[i].IndexBufferVBO = 0; DrawObjectList[i].IndexBuffer = 0; DrawObjectList[i].VertexBufferDestrType = 1; // удалять в объекте DrawObjectList[i].RangeStart = 0; // делаем поворот геометрии объекта чтобы правильно сделать разлет частиц DrawObjectList[i].VertexCount = 0; int k = 0; int NeedInCur = NeedIn; int tricount = 0; // если 2 текстурных координаты, нужно убрать 2-ю... if ((Object->DrawObjectList[i].FVF_Format & 0x000000F) >= 2) { DrawObjectList[i].FVF_Format = (Object->DrawObjectList[i].FVF_Format & 0xFFFFFF0) | RI_1_TEX; } else { DrawObjectList[i].FVF_Format = Object->DrawObjectList[i].FVF_Format; } DrawObjectList[i].Stride = Object->DrawObjectList[i].Stride; // если у нас включены и работают шейдеры, надо приготовить место для данных + изменить FVF_Format и шаг if (Setup.UseGLSL) { DrawObjectList[i].Stride = 3+3+6; DrawObjectList[i].FVF_Format = RI_3f_XYZ | RI_3f_NORMAL | RI_3_TEX | RI_2f_TEX; } // выделяем память для данных DrawObjectList[i].VertexBuffer = new float[DrawObjectList[i].Stride*Object->DrawObjectList[i].VertexCount]; // матрица для учета внутреннего состояния объекта float TransMatTMP[16]; Matrix44Identity(TransMatTMP); float TransMatTMPNorm[9]; Matrix33Identity(TransMatTMPNorm); // если нужно - создаем матрицу, иначе - копируем ее if (Object->DrawObjectList[i].Rotation.x != 0.0f || Object->DrawObjectList[i].Rotation.y != 0.0f || Object->DrawObjectList[i].Rotation.z != 0.0f) { Matrix44CreateRotate(TransMatTMP, Object->DrawObjectList[i].Rotation); Matrix33CreateRotate(TransMatTMPNorm, Object->DrawObjectList[i].Rotation); } Matrix44Translate(TransMatTMP, DrawObjectList[i].Location); Matrix33Mult(TransMatTMPNorm, Object->CurrentRotationMat); VECTOR3D TMP; for (int j=0; jDrawObjectList[i].VertexCount; j++) { if (NeedInCur <= 0) { int j1 = k*DrawObjectList[i].Stride; int j2; if (Object->DrawObjectList[i].IndexBuffer != 0) j2 = Object->DrawObjectList[i].IndexBuffer[Object->DrawObjectList[i].RangeStart+j]*Object->DrawObjectList[i].Stride; else j2 = (Object->DrawObjectList[i].RangeStart+j)*Object->DrawObjectList[i].Stride; TMP.x = Object->DrawObjectList[i].VertexBuffer[j2]; TMP.y = Object->DrawObjectList[i].VertexBuffer[j2+1]; TMP.z = Object->DrawObjectList[i].VertexBuffer[j2+2]; Matrix44CalcPoint(&TMP, TransMatTMP); Matrix33CalcPoint(&TMP, Object->CurrentRotationMat); // координаты DrawObjectList[i].VertexBuffer[j1] = TMP.x; DrawObjectList[i].VertexBuffer[j1+1] = TMP.y; DrawObjectList[i].VertexBuffer[j1+2] = TMP.z; // нормали TMP.x = Object->DrawObjectList[i].VertexBuffer[j2+3]; TMP.y = Object->DrawObjectList[i].VertexBuffer[j2+4]; TMP.z = Object->DrawObjectList[i].VertexBuffer[j2+5]; Matrix33CalcPoint(&TMP, TransMatTMPNorm); DrawObjectList[i].VertexBuffer[j1+3] = TMP.x; DrawObjectList[i].VertexBuffer[j1+4] = TMP.y; DrawObjectList[i].VertexBuffer[j1+5] = TMP.z; // текстура DrawObjectList[i].VertexBuffer[j1+6] = Object->DrawObjectList[i].VertexBuffer[j2+6]; DrawObjectList[i].VertexBuffer[j1+7] = Object->DrawObjectList[i].VertexBuffer[j2+7]; DrawObjectList[i].VertexCount ++; k++; if (tricount == 2) NeedInCur = NeedIn; } else { if (tricount == 2) NeedInCur --; } tricount ++; if (tricount >= 3) tricount=0; } DrawObjectList[i].Location = VECTOR3D(0.0f,0.0f,0.0f); DrawObjectList[i].Rotation = VECTOR3D(0.0f,0.0f,0.0f); TotalCount += DrawObjectList[i].VertexCount; } // расстояние от центра до крайней точки float Diag = (Object->Length*Object->Length)+ (Object->Height*Object->Height) + (Object->Width*Object->Width); // для каждого треугольника - свои данные int Count = 0; VECTOR3D TMP; ExplosionPieceData = new CExplosionPiece[TotalCount/3]; for (int j=0; jRadius); if (Acc > MeshAcc) Acc = MeshAcc+vw_Randf0; if (Acc < (-1.0f*MeshAcc)) Acc = (-1.0f*MeshAcc)-vw_Randf0; // записываем центр треугольника, оно же базовое ускорение + цент UV if (Setup.UseGLSL) { // Velocity/центр треугольника DrawObjectList[j].VertexBuffer[DrawObjectList[j].Stride*i+8] = ExplosionPieceData[Count].Velocity.x; DrawObjectList[j].VertexBuffer[DrawObjectList[j].Stride*i+9] = ExplosionPieceData[Count].Velocity.y; DrawObjectList[j].VertexBuffer[DrawObjectList[j].Stride*i+10] = ExplosionPieceData[Count].Velocity.z; DrawObjectList[j].VertexBuffer[DrawObjectList[j].Stride*(i+1)+8] = ExplosionPieceData[Count].Velocity.x; DrawObjectList[j].VertexBuffer[DrawObjectList[j].Stride*(i+1)+9] = ExplosionPieceData[Count].Velocity.y; DrawObjectList[j].VertexBuffer[DrawObjectList[j].Stride*(i+1)+10] = ExplosionPieceData[Count].Velocity.z; DrawObjectList[j].VertexBuffer[DrawObjectList[j].Stride*(i+2)+8] = ExplosionPieceData[Count].Velocity.x; DrawObjectList[j].VertexBuffer[DrawObjectList[j].Stride*(i+2)+9] = ExplosionPieceData[Count].Velocity.y; DrawObjectList[j].VertexBuffer[DrawObjectList[j].Stride*(i+2)+10] = ExplosionPieceData[Count].Velocity.z; // acc if (dist/Diag < 0.01f) { DrawObjectList[j].VertexBuffer[DrawObjectList[j].Stride*i+11] = Acc+4.0f*vw_Randf0; DrawObjectList[j].VertexBuffer[DrawObjectList[j].Stride*(i+1)+11] = DrawObjectList[j].VertexBuffer[DrawObjectList[j].Stride*i+11]; DrawObjectList[j].VertexBuffer[DrawObjectList[j].Stride*(i+2)+11] = DrawObjectList[j].VertexBuffer[DrawObjectList[j].Stride*i+11]; } else { DrawObjectList[j].VertexBuffer[DrawObjectList[j].Stride*i+11] = Acc; DrawObjectList[j].VertexBuffer[DrawObjectList[j].Stride*(i+1)+11] = Acc; DrawObjectList[j].VertexBuffer[DrawObjectList[j].Stride*(i+2)+11] = Acc; } } if (dist/Diag < 0.01f) ExplosionPieceData[Count].Velocity = ExplosionPieceData[Count].Velocity^(Acc+4.0f*vw_Randf0); else ExplosionPieceData[Count].Velocity = ExplosionPieceData[Count].Velocity^Acc; ExplosionPieceData[Count].Life = (Lifetime-1.0f)+vw_Randf1; if (ExplosionPieceData[Count].Life < 0.0f) ExplosionPieceData[Count].Life = 0.0f; // делаем анализ для ААBB, смотрим отлет частицы float tmpSpeed = ExplosionPieceData[Count].Velocity.x*ExplosionPieceData[Count].Velocity.x + ExplosionPieceData[Count].Velocity.y*ExplosionPieceData[Count].Velocity.y + ExplosionPieceData[Count].Velocity.z*ExplosionPieceData[Count].Velocity.z; if (tmpSpeed > AABBSpeed) AABBSpeed = tmpSpeed; Count++; } // если нужно, создаем vbo if (Setup.UseGLSL) { DrawObjectList[j].VertexBufferVBO = new unsigned int; if (!vw_BuildVBO(DrawObjectList[j].VertexCount, DrawObjectList[j].VertexBuffer, DrawObjectList[j].Stride, DrawObjectList[j].VertexBufferVBO)) { delete DrawObjectList[j].VertexBufferVBO; DrawObjectList[j].VertexBufferVBO=0; } } } // тк был квадрат, теперь вытягиваем нормальное значение AABBSpeed = sqrtf(AABBSpeed); // установки по шейдеру для объекта if (Setup.UseGLSL) { ShaderType = 2; // дельта скорости ShaderData[0] = 1.0f; // общий коэф расстояния ShaderData[1] = 0.0f; // установка нужных шейдеров Object3DGLSL[0][0] = vw_FindShaderByName("Explosion10"); Object3DGLSL[0][1] = vw_FindShaderByName("Explosion11"); Object3DGLSL[0][2] = vw_FindShaderByName("Explosion12"); Object3DGLSL[0][3] = vw_FindShaderByName("Explosion13"); Object3DGLSL[0][4] = vw_FindShaderByName("Explosion14"); Object3DGLSL[0][5] = vw_FindShaderByName("Explosion15"); Object3DGLSL[0][6] = vw_FindShaderByName("Explosion16"); Object3DGLSL[1][0] = vw_FindShaderByName("Explosion20"); Object3DGLSL[1][1] = vw_FindShaderByName("Explosion21"); Object3DGLSL[1][2] = vw_FindShaderByName("Explosion22"); Object3DGLSL[1][3] = vw_FindShaderByName("Explosion23"); Object3DGLSL[1][4] = vw_FindShaderByName("Explosion24"); Object3DGLSL[1][5] = vw_FindShaderByName("Explosion25"); Object3DGLSL[1][6] = vw_FindShaderByName("Explosion26"); } } // дальше, если не видем точку взрыва не делать... проверяем... if (!vw_BoxInFrustum(Location + AABB[6], Location + AABB[0])) { return; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // звуковые спец эффекты //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ float fVol = 1.0f; float Pitch = 1.0f - 0.1f*vw_Randf0; if (NeedExplosionSFX) switch (ExplType) { // малый взрыв case 1: // астероид Audio_PlaySound(33, fVol, Pitch, ExplLocation, false, 2); break; // взрыв case 2: // пришельцы Audio_PlaySound(7, fVol, Pitch, ExplLocation, false, 2); break; case 3: // земляне, пираты Audio_PlaySound(8, fVol, Pitch, ExplLocation, false, 2); break; // case 31: case 32: // внутренняя часть (пираты, земляне) //fVol = fVol/2; // ум. т.к. их там очень много Audio_PlaySound(8, fVol, Pitch, ExplLocation, false, 2); break; //case 33: case 34: // внутренняя часть (босс пришельцев) Audio_PlaySound(7, fVol, Pitch, ExplLocation, false, 2); break; } // делаем сотрясание камеры, если нужно switch (ExplType) { // малый взрыв case 1: // астероид GameCameraSetExplosion(ExplLocation, 0.2f); break; // взрыв case 2: // пришельцы GameCameraSetExplosion(ExplLocation, 0.5f); break; case 3: //case 31: case 32: // земляне, пираты GameCameraSetExplosion(ExplLocation, 0.5f); break; //case 33: case 34: // босс пришельцев GameCameraSetExplosion(ExplLocation, 0.5f); break; } }