2
0

bb_processor.h 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613
  1. //****************************************************************
  2. //*
  3. //* Author : Sergey Makeev aka Joker, 2003
  4. //*
  5. //*
  6. //****************************************************************
  7. #ifndef BILLBOARD_PARTICLE_PROCESSOR
  8. #define BILLBOARD_PARTICLE_PROCESSOR
  9. #include <string.h>
  10. #include <stdarg.h>
  11. #include <stdio.h>
  12. #include "..\..\..\common_h\core.h"
  13. #include "..\..\..\common_h\templates.h"
  14. #include "..\..\..\common_h\render.h"
  15. //#include "..\..\..\common_h\QSort.h"
  16. #include "..\..\icommon\particle.h"
  17. #include "..\datasource\fieldlist.h"
  18. #include "nameparser.h"
  19. #include "..\..\service\particleservice.h"
  20. #include "..\..\manager\syncParams.h"
  21. class ParticleSystem;
  22. #define PARTICLE_CHUNK (2048)
  23. #define DISTORTION_NEAR (10.0f * 10.0f)
  24. #define DISTORTION_MAX_DIST ((60.0f * 60.0f) + DISTORTION_NEAR)
  25. #define DISTORTION_RADIUS (1.0f / DISTORTION_MAX_DIST)
  26. #define UV_TX1 0
  27. #define UV_TX2 2
  28. #define UV_TY1 3
  29. #define UV_TY2 1
  30. //! Проверка видимости сферы в frustum'e камеры
  31. __forceinline bool SphereIsVisibleInFrustum (const Plane *frustum, const Vector& SphereCenter, float SphereRadius)
  32. {
  33. //Отсекаем только левый/правый/нижний плоскости
  34. for(long p = 0; p < 3; p++)
  35. if(((SphereCenter | frustum[p].n) - frustum[p].d) < -SphereRadius) return false;
  36. return true;
  37. }
  38. template <class TYPE>
  39. class FastQSortParticles
  40. {
  41. public:
  42. __forceinline void QSort(int (*compare_f)(TYPE,TYPE,void* ptr), TYPE* ArrayToSort, int uCount, void* ptr)
  43. {
  44. if (uCount <= 0) return;
  45. QSortRecursive (compare_f, ArrayToSort, 0, (uCount-1), ptr);
  46. }
  47. protected:
  48. __forceinline void QSortRecursive(int (*compare_func)(TYPE,TYPE,void* ptr), TYPE* pArr, int d, int h, void* ptr)
  49. {
  50. int i,j;
  51. TYPE str;
  52. begin:
  53. i = h;
  54. j = d;
  55. str = pArr[(d+h)>>1];
  56. do
  57. {
  58. while (compare_func (pArr[j], str, ptr) && (j < h)) j++;
  59. while (compare_func (str, pArr[i], ptr) && (i > d)) i--;
  60. if ( i >= j )
  61. {
  62. if ( i != j )
  63. {
  64. TYPE zal;
  65. zal = pArr[i];
  66. pArr[i] = pArr[j];
  67. pArr[j] = zal;
  68. }
  69. i--;
  70. j++;
  71. }
  72. } while (j <= i);
  73. if (d < i)
  74. {
  75. QSortRecursive(compare_func, pArr,d,i, ptr);
  76. }
  77. if (j < h)
  78. {
  79. d = j;
  80. goto begin;
  81. }
  82. }
  83. };
  84. class IGMXService;
  85. enum ParticleTypeForTemplateFunc
  86. {
  87. PTYPE_NORMAL = 0,
  88. PTYPE_NORMAL_XZ = 1,
  89. PTYPE_DISTORTED = 2,
  90. PTYPE_DISTORTED_XZ = 3,
  91. PTYPE_FORCE_DWORD = 0x7fffffff
  92. };
  93. class BillBoardProcessor
  94. {
  95. stack<dword> freeParticlesIdx;
  96. IGMXService* pGEOServ;
  97. GeomNameParser Parser;
  98. array<BB_ParticleData> particlesData;
  99. array<dword> ParticlesIdx;
  100. FastQSortParticles<dword> ParticleSorter;
  101. __forceinline void AllocParticles ()
  102. {
  103. DWORD dwStart = particlesData.Size();
  104. particlesData.AddElements(PARTICLE_CHUNK);
  105. for (DWORD n = dwStart; n < particlesData.Size(); n++)
  106. {
  107. freeParticlesIdx.Push(n);
  108. }
  109. }
  110. //Считает расстояние до билбоардов
  111. DWORD CalcDistanceToCamera (const Matrix& mView);
  112. //Функция сравнения при сортировке
  113. __forceinline static BOOL CompareFunction (dword e1, dword e2, void* ptr)
  114. {
  115. BillBoardProcessor* proc = (BillBoardProcessor*)ptr;
  116. if (proc->particlesData[e1].CamDistance > proc->particlesData[e2].CamDistance)
  117. {
  118. return true;
  119. }
  120. return false;
  121. }
  122. dword AllocParticle ();
  123. void FreeParticle (dword dwIndex);
  124. template <ParticleTypeForTemplateFunc _particleType>
  125. __forceinline bool UniformBuild(const Plane* Frustum, const Matrix& matView, RECT_VERTEX * __restrict vertsData, DWORD & particlesNeedToRender)
  126. {
  127. bool bHaveDistortParticles = false;
  128. DWORD ParticlesCount = 0;
  129. Vector SpeedVector;
  130. Color particleColor;
  131. Vector4 UV_WH1;
  132. Vector4 UV_WH2;
  133. for (DWORD j = 0; j < ParticlesIdx.Size(); j++)
  134. {
  135. dword dwParticleIdx = ParticlesIdx[j];
  136. BB_ParticleData* pR = &particlesData[dwParticleIdx];
  137. if (pR->Visible == false) continue;
  138. const Vector &vPos = pR->RenderPos;
  139. if (!SphereIsVisibleInFrustum(Frustum, vPos, 1.8f))
  140. {
  141. continue;
  142. }
  143. //этого if не должно быть... так как он определен на этапе компиляции...
  144. //------------------------------------------------------------------------------------
  145. if (_particleType == PTYPE_NORMAL)
  146. {
  147. if (ParticlesCount >= MAX_BILLBOARDS_TYPE0)
  148. {
  149. break;
  150. }
  151. if (pR->distorted == true)
  152. {
  153. bHaveDistortParticles = true;
  154. continue;
  155. }
  156. if (pR->xz_align == true)
  157. {
  158. continue;
  159. }
  160. }
  161. //------------------------------------------------------------------------------------
  162. //этого if не должно быть... так как он определен на этапе компиляции...
  163. //------------------------------------------------------------------------------------
  164. if (_particleType == PTYPE_DISTORTED)
  165. {
  166. if (ParticlesCount >= MAX_BILLBOARDS_TYPE2)
  167. {
  168. break;
  169. }
  170. if (pR->distorted == false)
  171. {
  172. continue;
  173. }
  174. if (pR->xz_align == true)
  175. {
  176. continue;
  177. }
  178. if (pR->CamDistance > DISTORTION_MAX_DIST)
  179. {
  180. continue;
  181. }
  182. }
  183. //------------------------------------------------------------------------------------
  184. //этого if не должно быть... так как он определен на этапе компиляции...
  185. //------------------------------------------------------------------------------------
  186. if (_particleType == PTYPE_NORMAL_XZ)
  187. {
  188. if (ParticlesCount >= MAX_BILLBOARDS_TYPE1)
  189. {
  190. break;
  191. }
  192. if (pR->distorted == true)
  193. {
  194. bHaveDistortParticles = true;
  195. continue;
  196. }
  197. if (pR->xz_align == false)
  198. {
  199. continue;
  200. }
  201. }
  202. //------------------------------------------------------------------------------------
  203. //этого if не должно быть... так как он определен на этапе компиляции...
  204. //------------------------------------------------------------------------------------
  205. if (_particleType == PTYPE_DISTORTED_XZ)
  206. {
  207. if (ParticlesCount >= MAX_BILLBOARDS_TYPE3)
  208. {
  209. break;
  210. }
  211. if (pR->distorted == false)
  212. {
  213. continue;
  214. }
  215. if (pR->xz_align != true)
  216. {
  217. continue;
  218. }
  219. if (pR->CamDistance > DISTORTION_MAX_DIST)
  220. {
  221. continue;
  222. }
  223. }
  224. //------------------------------------------------------------------------------------
  225. bool SpeedOriented = pR->SpeedOriented;
  226. float fSize = pR->Graph_Size->GetValue(pR->ElapsedTime, pR->LifeTime, pR->SizeK);
  227. float fIncSize = pR->Graph_SizeInc->GetValue(pR->ElapsedTime, pR->LifeTime, pR->SizeK);
  228. fSize = (pR->fInitialSize * (fSize * 0.01f)) + fIncSize;
  229. fSize = fSize * pR->fAllsystemScale;
  230. if (fSize <= 0.001f) continue;
  231. float fAngle = pR->RenderAngle;
  232. particleColor = pR->Graph_Color->GetValue(pR->ElapsedTime, pR->LifeTime, pR->ColorK);
  233. float particleColorMul = pR->Graph_ColorMul->GetValue(pR->ElapsedTime, pR->LifeTime, pR->AlphaK);
  234. particleColor = particleColor * particleColorMul;
  235. float Alpha = pR->Graph_Transparency->GetValue(pR->ElapsedTime, pR->LifeTime, pR->AlphaK);
  236. Alpha = Alpha * 0.01f;
  237. Alpha = 1.0f - Alpha;
  238. if (Alpha < 0.0f) Alpha = 0.0f;
  239. if (Alpha > 1.0f) Alpha = 1.0f;
  240. particleColor.a = Alpha;
  241. float AddPower;
  242. //этого if не должно быть... так как он определен на этапе компиляции...
  243. //------------------------------------------------------------------------------------
  244. if (_particleType == PTYPE_NORMAL || _particleType == PTYPE_NORMAL_XZ)
  245. {
  246. //обычние партиклы
  247. AddPower = pR->graph_AddPower->GetValue(pR->ElapsedTime, pR->LifeTime, pR->AddPowerK);
  248. AddPower = AddPower * 0.01f;
  249. AddPower = 1.0f - AddPower;
  250. if (AddPower < 0.0f) AddPower = 0.0f;
  251. if (AddPower > 1.0f) AddPower = 1.0f;
  252. } else
  253. {
  254. //distorted партиклы
  255. //Скалируем силу бампа от дистанции так, что бы на расстоянии от 10 до 60 метров...
  256. AddPower = (pR->distorted_pow->GetValue(pR->ElapsedTime, pR->LifeTime, pR->distorted_pow_K) * 0.01f);
  257. float distanceMultipler = 1.0f - Clampf((pR->CamDistance - DISTORTION_NEAR) * DISTORTION_RADIUS);
  258. AddPower = AddPower * distanceMultipler;
  259. }
  260. float LightPower = pR->Graph_LightK->GetValue(pR->ElapsedTime, pR->LifeTime, pR->LightK_K);
  261. LightPower = LightPower * 0.01f;
  262. if (LightPower > 1.0f) LightPower = 1.0f;
  263. if (LightPower < 0.0f) LightPower = 0.0f;
  264. float AmbientPower = pR->Graph_AmbientK->GetValue(pR->ElapsedTime, pR->LifeTime, pR->LightK_K);
  265. AmbientPower = AmbientPower * 0.01f;
  266. if (AmbientPower > 1.0f) AmbientPower = 1.0f;
  267. if (AmbientPower < 0.0f) AmbientPower = 0.0f;
  268. float FrameIndex = pR->Graph_Frames->GetValue(pR->ElapsedTime, pR->LifeTime, pR->FrameK);
  269. float DirAngle = 0.0f;
  270. float ScaleF = 1.0f;
  271. if (SpeedOriented)
  272. {
  273. //этого if не должно быть... так как он определен на этапе компиляции...
  274. //------------------------------------------------------------------------------------
  275. if (_particleType == PTYPE_NORMAL || _particleType == PTYPE_DISTORTED)
  276. {
  277. SpeedVector = pR->Velocity;
  278. if (pR->localMode)
  279. {
  280. pR->EmitterGUID->GetSystemTransform(pR->matWorld);
  281. SpeedVector = pR->matWorld.MulNormal(SpeedVector);
  282. }
  283. SpeedVector = matView.MulNormal(SpeedVector);
  284. SpeedVector.Normalize();
  285. FrameIndex *= (1.0f + SpeedVector.z)*0.5f;
  286. SpeedVector.z = SpeedVector.y;
  287. DirAngle = SpeedVector.GetAY(pR->OldRenderAngle);
  288. pR->OldRenderAngle = DirAngle;
  289. }
  290. //------------------------------------------------------------------------------------
  291. //этого if не должно быть... так как он определен на этапе компиляции...
  292. //------------------------------------------------------------------------------------
  293. if (_particleType == PTYPE_NORMAL_XZ || _particleType == PTYPE_DISTORTED_XZ)
  294. {
  295. SpeedVector = pR->Velocity;
  296. if (pR->localMode)
  297. {
  298. pR->EmitterGUID->GetSystemTransform(pR->matWorld);
  299. SpeedVector = pR->matWorld.MulNormal(SpeedVector);
  300. }
  301. SpeedVector.y = 0.0f;
  302. DirAngle = SpeedVector.GetAY(pR->OldRenderAngle);
  303. fAngle = DirAngle;
  304. }
  305. //------------------------------------------------------------------------------------
  306. }
  307. long FrameIndexLong = fftol(FrameIndex);
  308. float FrameBlendK = 1.0f - (FrameIndex - FrameIndexLong);
  309. //этого if не должно быть... так как он определен на этапе компиляции...
  310. //------------------------------------------------------------------------------------
  311. if (_particleType == PTYPE_NORMAL || _particleType == PTYPE_NORMAL_XZ)
  312. {
  313. //обычние партиклы
  314. UV_WH1 = pR->Graph_UV->GetValue(FrameIndexLong);
  315. UV_WH2 = pR->Graph_UV->GetValue(FrameIndexLong+1);
  316. } else
  317. {
  318. //distorted партиклы
  319. float slide = pR->ElapsedTime * 0.2f;
  320. UV_WH1 = Vector4(slide+0.0f, slide+0.0f, slide+1.0f, slide+1.0f);
  321. UV_WH2 = Vector4(0.0f, 0.0f, 1.0f, 1.0f);
  322. }
  323. #ifndef _XBOX
  324. //Указатель получаем на текущую частицу
  325. RECT_VERTEX * pV = vertsData;
  326. //Считаем на следущую частицу
  327. vertsData += 4;
  328. pV[0].vRelativePos = Vector(-fSize, -fSize, 0.0f);
  329. pV[0].vColor = particleColor.v4;
  330. pV[0].tu1 = UV_WH1.v4[UV_TX1]; pV[0].tv1 = UV_WH1.v4[UV_TY1];
  331. pV[0].tu2 = UV_WH2.v4[UV_TX1]; pV[0].tv2 = UV_WH2.v4[UV_TY1];
  332. pV[0].angle = fAngle;
  333. pV[0].BlendK = FrameBlendK;
  334. pV[0].vParticlePos = vPos;
  335. pV[0].AddPowerK = AddPower;
  336. pV[0].LightPower = LightPower;
  337. pV[0].AlwaysAmbientK = AmbientPower;
  338. if (SpeedOriented)
  339. {
  340. pV[0].angle = DirAngle;
  341. pV[0].vRelativePos.y *= ScaleF;
  342. }
  343. pV[1].vRelativePos = Vector(-fSize, fSize, 0.0f);
  344. pV[1].vColor = particleColor.v4;
  345. pV[1].tu1 = UV_WH1.v4[UV_TX1]; pV[1].tv1 = UV_WH1.v4[UV_TY2];
  346. pV[1].tu2 = UV_WH2.v4[UV_TX1]; pV[1].tv2 = UV_WH2.v4[UV_TY2];
  347. pV[1].angle = fAngle;
  348. pV[1].BlendK = FrameBlendK;
  349. pV[1].vParticlePos = vPos;
  350. pV[1].AddPowerK = AddPower;
  351. pV[1].LightPower = LightPower;
  352. pV[1].AlwaysAmbientK = AmbientPower;
  353. if (SpeedOriented)
  354. {
  355. pV[1].angle = DirAngle;
  356. pV[1].vRelativePos.y *= ScaleF;
  357. }
  358. pV[2].vRelativePos = Vector(fSize, fSize, 0.0f);
  359. pV[2].vColor = particleColor.v4;
  360. pV[2].tu1 = UV_WH1.v4[UV_TX2]; pV[2].tv1 = UV_WH1.v4[UV_TY2];
  361. pV[2].tu2 = UV_WH2.v4[UV_TX2]; pV[2].tv2 = UV_WH2.v4[UV_TY2];
  362. pV[2].angle = fAngle;
  363. pV[2].BlendK = FrameBlendK;
  364. pV[2].vParticlePos = vPos;
  365. pV[2].AddPowerK = AddPower;
  366. pV[2].LightPower = LightPower;
  367. pV[2].AlwaysAmbientK = AmbientPower;
  368. if (SpeedOriented)
  369. {
  370. pV[2].angle = DirAngle;
  371. pV[2].vRelativePos.y *= ScaleF;
  372. }
  373. pV[3].vRelativePos = Vector(fSize, -fSize, 0.0f);
  374. pV[3].vColor = particleColor.v4;
  375. pV[3].tu1 = UV_WH1.v4[UV_TX2]; pV[3].tv1 = UV_WH1.v4[UV_TY1];
  376. pV[3].tu2 = UV_WH2.v4[UV_TX2]; pV[3].tv2 = UV_WH2.v4[UV_TY1];
  377. pV[3].angle = fAngle;
  378. pV[3].BlendK = FrameBlendK;
  379. pV[3].vParticlePos = vPos;
  380. pV[3].AddPowerK = AddPower;
  381. pV[3].LightPower = LightPower;
  382. pV[3].AlwaysAmbientK = AmbientPower;
  383. if (SpeedOriented)
  384. {
  385. pV[3].angle = DirAngle;
  386. pV[3].vRelativePos.y *= ScaleF;
  387. }
  388. #else
  389. //Указатель получаем на текущую частицу
  390. RECT_VERTEX * __restrict pV = vertsData;
  391. //Считаем на следущую частицу
  392. vertsData++;
  393. float uv1_xs = (UV_WH1.v4[UV_TX2] - UV_WH1.v4[UV_TX1]) * 0.5f;
  394. float uv1_ys = (UV_WH1.v4[UV_TY1] - UV_WH1.v4[UV_TY2]) * 0.5f;
  395. float uv1_xc = UV_WH1.v4[UV_TX1] + uv1_xs;
  396. float uv1_yc = UV_WH1.v4[UV_TY2] + uv1_ys;
  397. float uv2_xs = (UV_WH2.v4[UV_TX2] - UV_WH2.v4[UV_TX1]) * 0.5f;
  398. float uv2_ys = (UV_WH2.v4[UV_TY1] - UV_WH2.v4[UV_TY2]) * 0.5f;
  399. float uv2_xc = UV_WH2.v4[UV_TX1] + uv2_xs;
  400. float uv2_yc = UV_WH2.v4[UV_TY2] + uv2_ys;
  401. pV->vRelativePos = Vector(fSize, uv1_xs, uv2_xs);
  402. pV->vColor = particleColor.v4;
  403. pV->tu1 = uv1_xc; pV->tv1 = uv1_yc;
  404. pV->tu2 = uv2_xc; pV->tv2 = uv2_yc;
  405. pV->angle = fAngle;
  406. pV->BlendK = FrameBlendK;
  407. pV->vParticlePos = vPos;
  408. pV->AddPowerK = AddPower;
  409. pV->LightPower = LightPower;
  410. pV->AlwaysAmbientK = AmbientPower;
  411. if (SpeedOriented)
  412. {
  413. pV->angle = DirAngle;
  414. pV->vRelativePos.y *= ScaleF;
  415. }
  416. #endif
  417. ParticlesCount++;
  418. } //Цикл по всем частицам...
  419. particlesNeedToRender = ParticlesCount;
  420. return bHaveDistortParticles;
  421. }
  422. CritSection access_to_particles;
  423. public:
  424. BillBoardProcessor ();
  425. ~BillBoardProcessor ();
  426. void DeleteDeadParticles ();
  427. //Из потока обновления
  428. void UpdateParticles (float RealDeltaTime);
  429. //не const SyncParams, потому что количество частиц там обновляет
  430. void BuildVertexBuffers (SyncParams & threadParams);
  431. //Из разных потоков (надо синхронизировать....)
  432. void AddParticle (const Vector& addVel, ParticleSystem* pSystem, const Vector& velocity_dir, const Vector& pos, const Matrix& matWorld, float EmitterTime, float EmitterLifeTime, FieldList* pFields, DWORD* pActiveCount, IEmitter* dwGUID, float fTimeScale, float fScale, bool bForceLocalMode);
  433. DWORD GetCount ();
  434. void DeleteWithGUID (IEmitter* dwGUID);
  435. void Clear ();
  436. //из основного потока
  437. bool Draw (const ParticleVB & renderVB, IIBuffer * pIBuffer, bool bSoftParticlesSupport);
  438. void DrawDistorted (const ParticleVB & renderVB, IIBuffer * pIBuffer);
  439. static BillBoardProcessor* singleton;
  440. static IRender* pRS;
  441. ShaderId shader_particles[3];
  442. ShaderId shader_particlesXZ[3];
  443. ShaderId shader_particles_distor[2];
  444. ShaderId shader_particlesXZ_distor[2];
  445. static CritSection draw_particles;
  446. };
  447. #endif