PageRenderTime 67ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/xbmc/visualizations/Milkdrop/vis_milkdrop/milkdropfs.cpp

http://github.com/xbmc/xbmc
C++ | 3791 lines | 2280 code | 486 blank | 1025 comment | 356 complexity | 787dd83e37422f1a7c78d74f419bf83e MD5 | raw file
Possible License(s): GPL-3.0, CC-BY-SA-3.0, LGPL-2.0, 0BSD, Unlicense, GPL-2.0, AGPL-1.0, BSD-3-Clause, LGPL-2.1, LGPL-3.0
  1. /*
  2. LICENSE
  3. -------
  4. Copyright 2005 Nullsoft, Inc.
  5. All rights reserved.
  6. Redistribution and use in source and binary forms, with or without modification,
  7. are permitted provided that the following conditions are met:
  8. * Redistributions of source code must retain the above copyright notice,
  9. this list of conditions and the following disclaimer.
  10. * Redistributions in binary form must reproduce the above copyright notice,
  11. this list of conditions and the following disclaimer in the documentation
  12. and/or other materials provided with the distribution.
  13. * Neither the name of Nullsoft nor the names of its contributors may be used to
  14. endorse or promote products derived from this software without specific prior written permission.
  15. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
  16. IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
  17. FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  18. CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  19. DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  20. DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
  21. IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  22. OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  23. */
  24. #include "plugin.h"
  25. //#include "resource.h"
  26. #include "support.h"
  27. #include "evallib\eval.h" // for math. expr. eval - thanks Francis! (in SourceOffSite, it's the 'vis_avs\evallib' project.)
  28. #include "evallib\compiler.h"
  29. #include "utility.h"
  30. #include <stdlib.h>
  31. #include <stdio.h>
  32. //#include <ddraw.h>
  33. //#include <d3dcaps.h>
  34. #include <assert.h>
  35. #include <math.h>
  36. //#include <shellapi.h>
  37. #define D3DCOLOR_RGBA_01(r,g,b,a) D3DCOLOR_RGBA(((int)(r*255)),((int)(g*255)),((int)(b*255)),((int)(a*255)))
  38. #define FRAND ((rand() % 7381)/7380.0f)
  39. //#define D3D_OVERLOADS
  40. #define VERT_CLIP 0.75f // warning: top/bottom can get clipped if you go < 0.65!
  41. //extern CPlugin* g_plugin; // declared in main.cpp
  42. //extern bool g_bDebugOutput; // declared in support.cpp
  43. int g_title_font_sizes[] =
  44. {
  45. // NOTE: DO NOT EXCEED 64 FONTS HERE.
  46. 6, 8, 10, 12, 14, 16,
  47. 20, 26, 32, 38, 44, 50, 56,
  48. 64, 72, 80, 88, 96, 104, 112, 120, 128, 136, 144,
  49. 160, 192, 224, 256, 288, 320, 352, 384, 416, 448,
  50. 480, 512 /**/
  51. };
  52. //#define COMPILE_MULTIMON_STUBS 1
  53. //#include <multimon.h>
  54. // This function evaluates whether the floating-point
  55. // control Word is set to single precision/round to nearest/
  56. // exceptions disabled. If not, the
  57. // function changes the control Word to set them and returns
  58. // TRUE, putting the old control Word value in the passback
  59. // location pointed to by pwOldCW.
  60. BOOL MungeFPCW( WORD *pwOldCW )
  61. {
  62. BOOL ret = FALSE;
  63. WORD wTemp, wSave;
  64. __asm fstcw wSave
  65. if (wSave & 0x300 || // Not single mode
  66. 0x3f != (wSave & 0x3f) || // Exceptions enabled
  67. wSave & 0xC00) // Not round to nearest mode
  68. {
  69. __asm
  70. {
  71. mov ax, wSave
  72. and ax, not 300h ;; single mode
  73. or ax, 3fh ;; disable all exceptions
  74. and ax, not 0xC00 ;; round to nearest mode
  75. mov wTemp, ax
  76. fldcw wTemp
  77. }
  78. ret = TRUE;
  79. }
  80. if (pwOldCW) *pwOldCW = wSave;
  81. return ret;
  82. }
  83. void RestoreFPCW(WORD wSave)
  84. {
  85. __asm fldcw wSave
  86. }
  87. int GetNumToSpawn(float fTime, float fDeltaT, float fRate, float fRegularity, int iNumSpawnedSoFar)
  88. {
  89. // PARAMETERS
  90. // ------------
  91. // fTime: sum of all fDeltaT's so far (excluding this one)
  92. // fDeltaT: time window for this frame
  93. // fRate: avg. rate (spawns per second) of generation
  94. // fRegularity: regularity of generation
  95. // 0.0: totally chaotic
  96. // 0.2: getting chaotic / very jittered
  97. // 0.4: nicely jittered
  98. // 0.6: slightly jittered
  99. // 0.8: almost perfectly regular
  100. // 1.0: perfectly regular
  101. // iNumSpawnedSoFar: the total number of spawnings so far
  102. //
  103. // RETURN VALUE
  104. // ------------
  105. // The number to spawn for this frame (add this to your net count!).
  106. //
  107. // COMMENTS
  108. // ------------
  109. // The spawn values returned will, over time, match
  110. // (within 1%) the theoretical totals expected based on the
  111. // amount of time passed and the average generation rate.
  112. //
  113. // UNRESOLVED ISSUES
  114. // -----------------
  115. // actual results of mixed gen. (0 < reg < 1) are about 1% too low
  116. // in the long run (vs. analytical expectations). Decided not
  117. // to bother fixing it since it's only 1% (and VERY consistent).
  118. float fNumToSpawnReg;
  119. float fNumToSpawnIrreg;
  120. float fNumToSpawn;
  121. // compute # spawned based on regular generation
  122. fNumToSpawnReg = ((fTime + fDeltaT) * fRate) - iNumSpawnedSoFar;
  123. // compute # spawned based on irregular (random) generation
  124. if (fDeltaT <= 1.0f / fRate)
  125. {
  126. // case 1: avg. less than 1 spawn per frame
  127. if ((rand() % 16384)/16384.0f < fDeltaT * fRate)
  128. fNumToSpawnIrreg = 1.0f;
  129. else
  130. fNumToSpawnIrreg = 0.0f;
  131. }
  132. else
  133. {
  134. // case 2: avg. more than 1 spawn per frame
  135. fNumToSpawnIrreg = fDeltaT * fRate;
  136. fNumToSpawnIrreg *= 2.0f*(rand() % 16384)/16384.0f;
  137. }
  138. // get linear combo. of regular & irregular
  139. fNumToSpawn = fNumToSpawnReg*fRegularity + fNumToSpawnIrreg*(1.0f - fRegularity);
  140. // round to nearest integer for result
  141. return (int)(fNumToSpawn + 0.49f);
  142. }
  143. /*
  144. char szHelp[] =
  145. {
  146. // note: this is a string-of-null-terminated-strings; the whole thing ends with a double null termination.
  147. // each substring will be drawn on its own line, and the strings are drawn in BOTTOM-UP order..
  148. // (this is just an effort to keep the file size low)
  149. "ESC: exit\0"
  150. " \0"
  151. "F9: toggle stereo 3D mode\0"
  152. "F8: change directory/drive\0"
  153. "F7: refresh milk_msg.ini\0"
  154. "F6: show preset rating\0"
  155. "F5: show fps\0"
  156. "F4: show preset name\0"
  157. "F2,F3: show song title,length\0"
  158. "F1: show help\0"
  159. " \0"
  160. "N: show per-frame variable moNitor\0"
  161. "S: save preset\0"
  162. "M: (preset editing) menu\0"
  163. " \0"
  164. "scroll lock: locks current preset\0"
  165. "+/-: rate current preset\0"
  166. "L: load specific preset\0"
  167. "R: toggle random(/sequential) preset order\0"
  168. "H: instant Hard cut (to next preset)\0"
  169. "spacebar: transition to next preset\0"
  170. " \0"
  171. "left/right arrows: seek 5 sec. [+SHIFT=seek 30]\0"
  172. "up/down arrows: adjust volume\0"
  173. "P: playlist\0"
  174. "U: toggle shuffle\0"
  175. "z/x/c/v/b: prev/play/pause/stop/next\0"
  176. " \0"
  177. "Y/K: enter custom message/sprite mode [see docs!]\0"
  178. "##: show custom message/sprite (##=00-99)\0"
  179. "T: launch song title animation\0"
  180. "\0\0"
  181. };
  182. */
  183. bool CPlugin::OnResizeTextWindow()
  184. {
  185. /*
  186. if (!m_hTextWnd)
  187. return false;
  188. RECT rect;
  189. GetClientRect(m_hTextWnd, &rect);
  190. if (rect.right - rect.left != m_nTextWndWidth ||
  191. rect.bottom - rect.top != m_nTextWndHeight)
  192. {
  193. m_nTextWndWidth = rect.right - rect.left;
  194. m_nTextWndHeight = rect.bottom - rect.top;
  195. // first, resize fonts if necessary
  196. //if (!InitFont())
  197. //return false;
  198. // then resize the memory bitmap used for double buffering
  199. if (m_memDC)
  200. {
  201. SelectObject(m_memDC, m_oldBM); // delete our doublebuffer
  202. DeleteObject(m_memDC);
  203. DeleteObject(m_memBM);
  204. m_memDC = NULL;
  205. m_memBM = NULL;
  206. m_oldBM = NULL;
  207. }
  208. HDC hdc = GetDC(m_hTextWnd);
  209. if (!hdc) return false;
  210. m_memDC = CreateCompatibleDC(hdc);
  211. m_memBM = CreateCompatibleBitmap(hdc, rect.right - rect.left, rect.bottom - rect.top);
  212. m_oldBM = (HBITMAP)SelectObject(m_memDC,m_memBM);
  213. ReleaseDC(m_hTextWnd, hdc);
  214. // save new window pos
  215. WriteRealtimeConfig();
  216. }*/
  217. return true;
  218. }
  219. void CPlugin::ClearGraphicsWindow()
  220. {
  221. // clear the window contents, to avoid a 1-pixel-thick border of noise that sometimes sticks around
  222. /*
  223. RECT rect;
  224. GetClientRect(GetPluginWindow(), &rect);
  225. HDC hdc = GetDC(GetPluginWindow());
  226. FillRect(hdc, &rect, m_hBlackBrush);
  227. ReleaseDC(GetPluginWindow(), hdc);
  228. */
  229. }
  230. /*
  231. bool CPlugin::OnResizeGraphicsWindow()
  232. {
  233. // NO LONGER NEEDED, SINCE PLUGIN SHELL CREATES A NEW DIRECTX
  234. // OBJECT WHENEVER WINDOW IS RESIZED.
  235. }
  236. */
  237. bool CPlugin::RenderStringToTitleTexture() // m_szSongMessage
  238. {
  239. #if 0
  240. if (!m_lpDDSTitle) // this *can* be NULL, if not much video mem!
  241. return false;
  242. if (m_supertext.szText[0]==0)
  243. return false;
  244. LPDIRECT3DDEVICE8 lpDevice = GetDevice();
  245. if (!lpDevice)
  246. return false;
  247. char szTextToDraw[512];
  248. sprintf(szTextToDraw, " %s ", m_supertext.szText); //add a space @ end for italicized fonts; and at start, too, because it's centered!
  249. // Remember the original backbuffer and zbuffer
  250. LPDIRECT3DSURFACE8 pBackBuffer, pZBuffer;
  251. lpDevice->GetRenderTarget( &pBackBuffer );
  252. // lpDevice->GetDepthStencilSurface( &pZBuffer );
  253. // set render target to m_lpDDSTitle
  254. {
  255. lpDevice->SetTexture(0, NULL);
  256. IDirect3DSurface8* pNewTarget = NULL;
  257. if (m_lpDDSTitle->GetSurfaceLevel(0, &pNewTarget) != D3D_OK)
  258. {
  259. SafeRelease(pBackBuffer);
  260. // SafeRelease(pZBuffer);
  261. return false;
  262. }
  263. lpDevice->SetRenderTarget(pNewTarget, NULL);
  264. pNewTarget->Release();
  265. lpDevice->SetTexture(0, NULL);
  266. }
  267. // clear the texture to black
  268. {
  269. lpDevice->SetVertexShader( WFVERTEX_FORMAT );
  270. lpDevice->SetTexture(0, NULL);
  271. lpDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE );
  272. // set up a quad
  273. WFVERTEX verts[4];
  274. for (int i=0; i<4; i++)
  275. {
  276. verts[i].x = (i%2==0) ? -1 : 1;
  277. verts[i].y = (i/2==0) ? -1 : 1;
  278. verts[i].z = 0;
  279. verts[i].Diffuse = 0xFF000000;
  280. }
  281. lpDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, verts, sizeof(WFVERTEX));
  282. }
  283. /*// 1. clip title if too many chars
  284. if (m_supertext.bIsSongTitle)
  285. {
  286. // truncate song title if too long; don't clip custom messages, though!
  287. int clip_chars = 32;
  288. int user_title_size = GetFontHeight(SONGTITLE_FONT);
  289. #define MIN_CHARS 8 // max clip_chars *for BIG FONTS*
  290. #define MAX_CHARS 64 // max clip chars *for tiny fonts*
  291. float t = (user_title_size-10)/(float)(128-10);
  292. t = min(1,max(0,t));
  293. clip_chars = (int)(MAX_CHARS - (MAX_CHARS-MIN_CHARS)*t);
  294. if ((int)strlen(szTextToDraw) > clip_chars+3)
  295. lstrcpy(&szTextToDraw[clip_chars], "...");
  296. }*/
  297. bool ret = true;
  298. // use 2 lines; must leave room for bottom of 'g' characters and such!
  299. RECT rect;
  300. rect.left = 0;
  301. rect.right = m_nTitleTexSizeX;
  302. rect.top = m_nTitleTexSizeY* 1/21; // otherwise, top of '%' could be cut off (1/21 seems safe)
  303. rect.bottom = m_nTitleTexSizeY*17/21; // otherwise, bottom of 'g' could be cut off (18/21 seems safe, but we want some leeway)
  304. if (!m_supertext.bIsSongTitle)
  305. {
  306. // custom msg -> pick font to use that will best fill the texture
  307. HFONT gdi_font = NULL;
  308. LPD3DXFONT d3dx_font = NULL;
  309. int lo = 0;
  310. int hi = sizeof(g_title_font_sizes)/sizeof(int) - 1;
  311. // limit the size of the font used:
  312. //int user_title_size = GetFontHeight(SONGTITLE_FONT);
  313. //while (g_title_font_sizes[hi] > user_title_size*2 && hi>4)
  314. // hi--;
  315. RECT temp;
  316. while (1)//(lo < hi-1)
  317. {
  318. int mid = (lo+hi)/2;
  319. // create new gdi font at 'mid' size:
  320. gdi_font = CreateFont(g_title_font_sizes[mid], 0, 0, 0, m_supertext.bBold ? 900 : 400, m_supertext.bItal, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, m_fontinfo[SONGTITLE_FONT].bAntiAliased ? ANTIALIASED_QUALITY : DEFAULT_QUALITY, DEFAULT_PITCH, m_supertext.nFontFace);
  321. if (gdi_font)
  322. {
  323. // create new d3dx font at 'mid' size:
  324. if (D3DXCreateFont(lpDevice, gdi_font, &d3dx_font) == D3D_OK)
  325. {
  326. if (lo == hi-1)
  327. break; // DONE; but the 'lo'-size font is ready for use!
  328. // compute size of text if drawn w/font of THIS size:
  329. temp = rect;
  330. int h = d3dx_font->DrawText(szTextToDraw, -1, &temp, DT_SINGLELINE | DT_CALCRECT | DT_NOPREFIX, 0xFFFFFFFF);
  331. // adjust & prepare to reiterate:
  332. if (temp.right >= rect.right || h > rect.bottom-rect.top)
  333. hi = mid;
  334. else
  335. lo = mid;
  336. SafeRelease(d3dx_font);
  337. }
  338. DeleteObject(gdi_font); gdi_font=NULL;
  339. }
  340. }
  341. if (gdi_font && d3dx_font)
  342. {
  343. // do actual drawing + set m_supertext.nFontSizeUsed; use 'lo' size
  344. int h = d3dx_font->DrawText(szTextToDraw, -1, &temp, DT_SINGLELINE | DT_CALCRECT | DT_NOPREFIX | DT_CENTER, 0xFFFFFFFF);
  345. temp.left = 0;
  346. temp.right = m_nTitleTexSizeX; // now allow text to go all the way over, since we're actually drawing!
  347. temp.top = m_nTitleTexSizeY/2 - h/2;
  348. temp.bottom = m_nTitleTexSizeY/2 + h/2;
  349. m_supertext.nFontSizeUsed = d3dx_font->DrawText(szTextToDraw, -1, &temp, DT_SINGLELINE | DT_NOPREFIX | DT_CENTER, 0xFFFFFFFF);
  350. ret = true;
  351. }
  352. else
  353. {
  354. ret = false;
  355. }
  356. // clean up font:
  357. SafeRelease(d3dx_font);
  358. if (gdi_font) DeleteObject(gdi_font); gdi_font=NULL;
  359. }
  360. else // song title
  361. {
  362. RECT temp = rect;
  363. // do actual drawing + set m_supertext.nFontSizeUsed; use 'lo' size
  364. int h = m_d3dx_title_font_doublesize->DrawText(szTextToDraw, -1, &temp, DT_SINGLELINE | DT_CALCRECT | DT_NOPREFIX | DT_CENTER | DT_END_ELLIPSIS, 0xFFFFFFFF);
  365. temp.left = 0;
  366. temp.right = m_nTitleTexSizeX; // now allow text to go all the way over, since we're actually drawing!
  367. temp.top = m_nTitleTexSizeY/2 - h/2;
  368. temp.bottom = m_nTitleTexSizeY/2 + h/2;
  369. m_supertext.nFontSizeUsed = m_d3dx_title_font_doublesize->DrawText(szTextToDraw, -1, &temp, DT_SINGLELINE | DT_NOPREFIX | DT_CENTER | DT_END_ELLIPSIS, 0xFFFFFFFF);
  370. }
  371. // Change the rendertarget back to the original setup
  372. lpDevice->SetTexture(0, NULL);
  373. lpDevice->SetRenderTarget( pBackBuffer, NULL );
  374. SafeRelease(pBackBuffer);
  375. SafeRelease(pZBuffer);
  376. return ret;
  377. #endif
  378. return false;
  379. }
  380. void CPlugin::LoadPerFrameEvallibVars(CState* pState)
  381. {
  382. // load the 'var_pf_*' variables in this CState object with the correct values.
  383. // for vars that affect pixel motion, that means evaluating them at time==-1,
  384. // (i.e. no blending w/blendto value); the blending of the file dx/dy
  385. // will be done *after* execution of the per-vertex code.
  386. // for vars that do NOT affect pixel motion, evaluate them at the current time,
  387. // so that if they're blending, both states see the blended value.
  388. // 1. vars that affect pixel motion: (eval at time==-1)
  389. *pState->var_pf_zoom = (double)pState->m_fZoom.eval(-1);//GetTime());
  390. *pState->var_pf_zoomexp = (double)pState->m_fZoomExponent.eval(-1);//GetTime());
  391. *pState->var_pf_rot = (double)pState->m_fRot.eval(-1);//GetTime());
  392. *pState->var_pf_warp = (double)pState->m_fWarpAmount.eval(-1);//GetTime());
  393. *pState->var_pf_cx = (double)pState->m_fRotCX.eval(-1);//GetTime());
  394. *pState->var_pf_cy = (double)pState->m_fRotCY.eval(-1);//GetTime());
  395. *pState->var_pf_dx = (double)pState->m_fXPush.eval(-1);//GetTime());
  396. *pState->var_pf_dy = (double)pState->m_fYPush.eval(-1);//GetTime());
  397. *pState->var_pf_sx = (double)pState->m_fStretchX.eval(-1);//GetTime());
  398. *pState->var_pf_sy = (double)pState->m_fStretchY.eval(-1);//GetTime());
  399. // read-only:
  400. *pState->var_pf_time = (double)(GetTime() - m_fStartTime);
  401. *pState->var_pf_fps = (double)GetFps();
  402. *pState->var_pf_bass = (double)mysound.imm_rel[0];
  403. *pState->var_pf_mid = (double)mysound.imm_rel[1];
  404. *pState->var_pf_treb = (double)mysound.imm_rel[2];
  405. *pState->var_pf_bass_att = (double)mysound.avg_rel[0];
  406. *pState->var_pf_mid_att = (double)mysound.avg_rel[1];
  407. *pState->var_pf_treb_att = (double)mysound.avg_rel[2];
  408. *pState->var_pf_frame = (double)GetFrame();
  409. //*pState->var_pf_monitor = 0; -leave this as it was set in the per-frame INIT code!
  410. *pState->var_pf_q1 = pState->q_values_after_init_code[0];//0.0f;
  411. *pState->var_pf_q2 = pState->q_values_after_init_code[1];//0.0f;
  412. *pState->var_pf_q3 = pState->q_values_after_init_code[2];//0.0f;
  413. *pState->var_pf_q4 = pState->q_values_after_init_code[3];//0.0f;
  414. *pState->var_pf_q5 = pState->q_values_after_init_code[4];//0.0f;
  415. *pState->var_pf_q6 = pState->q_values_after_init_code[5];//0.0f;
  416. *pState->var_pf_q7 = pState->q_values_after_init_code[6];//0.0f;
  417. *pState->var_pf_q8 = pState->q_values_after_init_code[7];//0.0f;
  418. *pState->var_pf_monitor = pState->monitor_after_init_code;
  419. *pState->var_pf_progress = (GetTime() - m_fPresetStartTime) / (m_fNextPresetTime - m_fPresetStartTime);
  420. // 2. vars that do NOT affect pixel motion: (eval at time==now)
  421. *pState->var_pf_decay = (double)pState->m_fDecay.eval(GetTime());
  422. *pState->var_pf_wave_a = (double)pState->m_fWaveAlpha.eval(GetTime());
  423. *pState->var_pf_wave_r = (double)pState->m_fWaveR.eval(GetTime());
  424. *pState->var_pf_wave_g = (double)pState->m_fWaveG.eval(GetTime());
  425. *pState->var_pf_wave_b = (double)pState->m_fWaveB.eval(GetTime());
  426. *pState->var_pf_wave_x = (double)pState->m_fWaveX.eval(GetTime());
  427. *pState->var_pf_wave_y = (double)pState->m_fWaveY.eval(GetTime());
  428. *pState->var_pf_wave_mystery= (double)pState->m_fWaveParam.eval(GetTime());
  429. *pState->var_pf_wave_mode = (double)pState->m_nWaveMode; //?!?! -why won't it work if set to pState->m_nWaveMode???
  430. *pState->var_pf_ob_size = (double)pState->m_fOuterBorderSize.eval(GetTime());
  431. *pState->var_pf_ob_r = (double)pState->m_fOuterBorderR.eval(GetTime());
  432. *pState->var_pf_ob_g = (double)pState->m_fOuterBorderG.eval(GetTime());
  433. *pState->var_pf_ob_b = (double)pState->m_fOuterBorderB.eval(GetTime());
  434. *pState->var_pf_ob_a = (double)pState->m_fOuterBorderA.eval(GetTime());
  435. *pState->var_pf_ib_size = (double)pState->m_fInnerBorderSize.eval(GetTime());
  436. *pState->var_pf_ib_r = (double)pState->m_fInnerBorderR.eval(GetTime());
  437. *pState->var_pf_ib_g = (double)pState->m_fInnerBorderG.eval(GetTime());
  438. *pState->var_pf_ib_b = (double)pState->m_fInnerBorderB.eval(GetTime());
  439. *pState->var_pf_ib_a = (double)pState->m_fInnerBorderA.eval(GetTime());
  440. *pState->var_pf_mv_x = (double)pState->m_fMvX.eval(GetTime());
  441. *pState->var_pf_mv_y = (double)pState->m_fMvY.eval(GetTime());
  442. *pState->var_pf_mv_dx = (double)pState->m_fMvDX.eval(GetTime());
  443. *pState->var_pf_mv_dy = (double)pState->m_fMvDY.eval(GetTime());
  444. *pState->var_pf_mv_l = (double)pState->m_fMvL.eval(GetTime());
  445. *pState->var_pf_mv_r = (double)pState->m_fMvR.eval(GetTime());
  446. *pState->var_pf_mv_g = (double)pState->m_fMvG.eval(GetTime());
  447. *pState->var_pf_mv_b = (double)pState->m_fMvB.eval(GetTime());
  448. *pState->var_pf_mv_a = (double)pState->m_fMvA.eval(GetTime());
  449. *pState->var_pf_echo_zoom = (double)pState->m_fVideoEchoZoom.eval(GetTime());
  450. *pState->var_pf_echo_alpha = (double)pState->m_fVideoEchoAlpha.eval(GetTime());
  451. *pState->var_pf_echo_orient = (double)pState->m_nVideoEchoOrientation;
  452. // new in v1.04:
  453. *pState->var_pf_wave_usedots = (double)pState->m_bWaveDots;
  454. *pState->var_pf_wave_thick = (double)pState->m_bWaveThick;
  455. *pState->var_pf_wave_additive = (double)pState->m_bAdditiveWaves;
  456. *pState->var_pf_wave_brighten = (double)pState->m_bMaximizeWaveColor;
  457. *pState->var_pf_darken_center = (double)pState->m_bDarkenCenter;
  458. *pState->var_pf_gamma = (double)pState->m_fGammaAdj.eval(GetTime());
  459. *pState->var_pf_wrap = (double)pState->m_bTexWrap;
  460. *pState->var_pf_invert = (double)pState->m_bInvert;
  461. *pState->var_pf_brighten = (double)pState->m_bBrighten;
  462. *pState->var_pf_darken = (double)pState->m_bDarken;
  463. *pState->var_pf_solarize = (double)pState->m_bSolarize;
  464. *pState->var_pf_meshx = (double)m_nGridX;
  465. *pState->var_pf_meshy = (double)m_nGridY;
  466. }
  467. void CPlugin::RunPerFrameEquations()
  468. {
  469. // run per-frame calculations
  470. int num_reps = (m_pState->m_bBlending) ? 2 : 1;
  471. for (int rep=0; rep<num_reps; rep++)
  472. {
  473. CState *pState;
  474. if (rep==0)
  475. pState = m_pState;
  476. else
  477. pState = m_pOldState;
  478. // values that will affect the pixel motion (and will be automatically blended
  479. // LATER, when the results of 2 sets of these params creates 2 different U/V
  480. // meshes that get blended together.)
  481. LoadPerFrameEvallibVars(pState);
  482. // also do just a once-per-frame init for the *per-**VERTEX*** *READ-ONLY* variables
  483. // (the non-read-only ones will be reset/restored at the start of each vertex)
  484. *pState->var_pv_time = *pState->var_pf_time;
  485. *pState->var_pv_fps = *pState->var_pf_fps;
  486. *pState->var_pv_frame = *pState->var_pf_frame;
  487. *pState->var_pv_progress = *pState->var_pf_progress;
  488. *pState->var_pv_bass = *pState->var_pf_bass;
  489. *pState->var_pv_mid = *pState->var_pf_mid;
  490. *pState->var_pv_treb = *pState->var_pf_treb;
  491. *pState->var_pv_bass_att = *pState->var_pf_bass_att;
  492. *pState->var_pv_mid_att = *pState->var_pf_mid_att;
  493. *pState->var_pv_treb_att = *pState->var_pf_treb_att;
  494. *pState->var_pv_meshx = (double)m_nGridX;
  495. *pState->var_pv_meshy = (double)m_nGridY;
  496. //*pState->var_pv_monitor = *pState->var_pf_monitor;
  497. // execute once-per-frame expressions:
  498. #ifndef _NO_EXPR_
  499. if (pState->m_pf_codehandle)
  500. {
  501. resetVars(pState->m_pf_vars);
  502. if (pState->m_pf_codehandle)
  503. {
  504. executeCode(pState->m_pf_codehandle);
  505. }
  506. resetVars(NULL);
  507. }
  508. #endif
  509. // save some things for next frame:
  510. pState->monitor_after_init_code = *pState->var_pf_monitor;
  511. // save some things for per-vertex code:
  512. *pState->var_pv_q1 = *pState->var_pf_q1;
  513. *pState->var_pv_q2 = *pState->var_pf_q2;
  514. *pState->var_pv_q3 = *pState->var_pf_q3;
  515. *pState->var_pv_q4 = *pState->var_pf_q4;
  516. *pState->var_pv_q5 = *pState->var_pf_q5;
  517. *pState->var_pv_q6 = *pState->var_pf_q6;
  518. *pState->var_pv_q7 = *pState->var_pf_q7;
  519. *pState->var_pv_q8 = *pState->var_pf_q8;
  520. // (a few range checks:)
  521. *pState->var_pf_gamma = max(0 , min( 8, *pState->var_pf_gamma ));
  522. *pState->var_pf_echo_zoom = max(0.001, min( 1000, *pState->var_pf_echo_zoom));
  523. if (m_pState->m_bRedBlueStereo || m_bAlways3D)
  524. {
  525. // override wave colors
  526. *pState->var_pf_wave_r = 0.35f*(*pState->var_pf_wave_r) + 0.65f;
  527. *pState->var_pf_wave_g = 0.35f*(*pState->var_pf_wave_g) + 0.65f;
  528. *pState->var_pf_wave_b = 0.35f*(*pState->var_pf_wave_b) + 0.65f;
  529. }
  530. }
  531. if (m_pState->m_bBlending)
  532. {
  533. // For all variables that do NOT affect pixel motion, blend them NOW,
  534. // so later the user can just access m_pState->m_pf_whatever.
  535. double mix = (double)CosineInterp(m_pState->m_fBlendProgress);
  536. double mix2 = 1.0 - mix;
  537. *m_pState->var_pf_decay = mix*(*m_pState->var_pf_decay ) + mix2*(*m_pOldState->var_pf_decay );
  538. *m_pState->var_pf_wave_a = mix*(*m_pState->var_pf_wave_a ) + mix2*(*m_pOldState->var_pf_wave_a );
  539. *m_pState->var_pf_wave_r = mix*(*m_pState->var_pf_wave_r ) + mix2*(*m_pOldState->var_pf_wave_r );
  540. *m_pState->var_pf_wave_g = mix*(*m_pState->var_pf_wave_g ) + mix2*(*m_pOldState->var_pf_wave_g );
  541. *m_pState->var_pf_wave_b = mix*(*m_pState->var_pf_wave_b ) + mix2*(*m_pOldState->var_pf_wave_b );
  542. *m_pState->var_pf_wave_x = mix*(*m_pState->var_pf_wave_x ) + mix2*(*m_pOldState->var_pf_wave_x );
  543. *m_pState->var_pf_wave_y = mix*(*m_pState->var_pf_wave_y ) + mix2*(*m_pOldState->var_pf_wave_y );
  544. *m_pState->var_pf_wave_mystery = mix*(*m_pState->var_pf_wave_mystery) + mix2*(*m_pOldState->var_pf_wave_mystery);
  545. // wave_mode: exempt (integer)
  546. *m_pState->var_pf_ob_size = mix*(*m_pState->var_pf_ob_size ) + mix2*(*m_pOldState->var_pf_ob_size );
  547. *m_pState->var_pf_ob_r = mix*(*m_pState->var_pf_ob_r ) + mix2*(*m_pOldState->var_pf_ob_r );
  548. *m_pState->var_pf_ob_g = mix*(*m_pState->var_pf_ob_g ) + mix2*(*m_pOldState->var_pf_ob_g );
  549. *m_pState->var_pf_ob_b = mix*(*m_pState->var_pf_ob_b ) + mix2*(*m_pOldState->var_pf_ob_b );
  550. *m_pState->var_pf_ob_a = mix*(*m_pState->var_pf_ob_a ) + mix2*(*m_pOldState->var_pf_ob_a );
  551. *m_pState->var_pf_ib_size = mix*(*m_pState->var_pf_ib_size ) + mix2*(*m_pOldState->var_pf_ib_size );
  552. *m_pState->var_pf_ib_r = mix*(*m_pState->var_pf_ib_r ) + mix2*(*m_pOldState->var_pf_ib_r );
  553. *m_pState->var_pf_ib_g = mix*(*m_pState->var_pf_ib_g ) + mix2*(*m_pOldState->var_pf_ib_g );
  554. *m_pState->var_pf_ib_b = mix*(*m_pState->var_pf_ib_b ) + mix2*(*m_pOldState->var_pf_ib_b );
  555. *m_pState->var_pf_ib_a = mix*(*m_pState->var_pf_ib_a ) + mix2*(*m_pOldState->var_pf_ib_a );
  556. *m_pState->var_pf_mv_x = mix*(*m_pState->var_pf_mv_x ) + mix2*(*m_pOldState->var_pf_mv_x );
  557. *m_pState->var_pf_mv_y = mix*(*m_pState->var_pf_mv_y ) + mix2*(*m_pOldState->var_pf_mv_y );
  558. *m_pState->var_pf_mv_dx = mix*(*m_pState->var_pf_mv_dx ) + mix2*(*m_pOldState->var_pf_mv_dx );
  559. *m_pState->var_pf_mv_dy = mix*(*m_pState->var_pf_mv_dy ) + mix2*(*m_pOldState->var_pf_mv_dy );
  560. *m_pState->var_pf_mv_l = mix*(*m_pState->var_pf_mv_l ) + mix2*(*m_pOldState->var_pf_mv_l );
  561. *m_pState->var_pf_mv_r = mix*(*m_pState->var_pf_mv_r ) + mix2*(*m_pOldState->var_pf_mv_r );
  562. *m_pState->var_pf_mv_g = mix*(*m_pState->var_pf_mv_g ) + mix2*(*m_pOldState->var_pf_mv_g );
  563. *m_pState->var_pf_mv_b = mix*(*m_pState->var_pf_mv_b ) + mix2*(*m_pOldState->var_pf_mv_b );
  564. *m_pState->var_pf_mv_a = mix*(*m_pState->var_pf_mv_a ) + mix2*(*m_pOldState->var_pf_mv_a );
  565. *m_pState->var_pf_echo_zoom = mix*(*m_pState->var_pf_echo_zoom ) + mix2*(*m_pOldState->var_pf_echo_zoom );
  566. *m_pState->var_pf_echo_alpha = mix*(*m_pState->var_pf_echo_alpha ) + mix2*(*m_pOldState->var_pf_echo_alpha );
  567. *m_pState->var_pf_echo_orient = (mix < 0.5f) ? *m_pOldState->var_pf_echo_orient : *m_pState->var_pf_echo_orient;
  568. // added in v1.04:
  569. *m_pState->var_pf_wave_usedots = (mix < 0.5f) ? *m_pOldState->var_pf_wave_usedots : *m_pState->var_pf_wave_usedots ;
  570. *m_pState->var_pf_wave_thick = (mix < 0.5f) ? *m_pOldState->var_pf_wave_thick : *m_pState->var_pf_wave_thick ;
  571. *m_pState->var_pf_wave_additive= (mix < 0.5f) ? *m_pOldState->var_pf_wave_additive : *m_pState->var_pf_wave_additive;
  572. *m_pState->var_pf_wave_brighten= (mix < 0.5f) ? *m_pOldState->var_pf_wave_brighten : *m_pState->var_pf_wave_brighten;
  573. *m_pState->var_pf_darken_center= (mix < 0.5f) ? *m_pOldState->var_pf_darken_center : *m_pState->var_pf_darken_center;
  574. *m_pState->var_pf_gamma = mix*(*m_pState->var_pf_gamma ) + mix2*(*m_pOldState->var_pf_gamma );
  575. *m_pState->var_pf_wrap = (mix < 0.5f) ? *m_pOldState->var_pf_wrap : *m_pState->var_pf_wrap ;
  576. *m_pState->var_pf_invert = (mix < 0.5f) ? *m_pOldState->var_pf_invert : *m_pState->var_pf_invert ;
  577. *m_pState->var_pf_brighten = (mix < 0.5f) ? *m_pOldState->var_pf_brighten : *m_pState->var_pf_brighten ;
  578. *m_pState->var_pf_darken = (mix < 0.5f) ? *m_pOldState->var_pf_darken : *m_pState->var_pf_darken ;
  579. *m_pState->var_pf_solarize = (mix < 0.5f) ? *m_pOldState->var_pf_solarize : *m_pState->var_pf_solarize ;
  580. }
  581. }
  582. void CPlugin::RenderFrame(int bRedraw)
  583. {
  584. int i;
  585. float fDeltaT = 1.0f/GetFps();
  586. // update time
  587. /*
  588. float fDeltaT = (GetFrame()==0) ? 1.0f/30.0f : GetTime() - m_prev_time;
  589. DWORD dwTime = GetTickCount();
  590. float fDeltaT = (dwTime - m_dwPrevTickCount)*0.001f;
  591. if (GetFrame() > 64)
  592. {
  593. fDeltaT = (fDeltaT)*0.2f + 0.8f*(1.0f/m_fps);
  594. if (fDeltaT > 2.0f/m_fps)
  595. {
  596. char buf[64];
  597. sprintf(buf, "fixing time gap of %5.3f seconds", fDeltaT);
  598. dumpmsg(buf);
  599. fDeltaT = 1.0f/m_fps;
  600. }
  601. }
  602. m_dwPrevTickCount = dwTime;
  603. GetTime() += fDeltaT;
  604. */
  605. if (GetFrame()==0)
  606. {
  607. m_fStartTime = GetTime();
  608. m_fPresetStartTime = GetTime();
  609. }
  610. if (m_fNextPresetTime < 0)
  611. {
  612. float dt = m_fTimeBetweenPresetsRand * (rand()%1000)*0.001f;
  613. m_fNextPresetTime = GetTime() + m_fBlendTimeAuto + m_fTimeBetweenPresets + dt;
  614. }
  615. /*
  616. if (m_bPresetLockedByUser || m_bPresetLockedByCode)
  617. {
  618. // if the user has the preset LOCKED, or if they're in the middle of
  619. // saving it, then keep extending the time at which the auto-switch will occur
  620. // (by the length of this frame).
  621. m_fPresetStartTime += fDeltaT;
  622. m_fNextPresetTime += fDeltaT;
  623. }*/
  624. // update fps
  625. /*
  626. if (GetFrame() < 4)
  627. {
  628. m_fps = 0.0f;
  629. }
  630. else if (GetFrame() <= 64)
  631. {
  632. m_fps = GetFrame() / (float)(GetTime() - m_fTimeHistory[0]);
  633. }
  634. else
  635. {
  636. m_fps = 64.0f / (float)(GetTime() - m_fTimeHistory[m_nTimeHistoryPos]);
  637. }
  638. m_fTimeHistory[m_nTimeHistoryPos] = GetTime();
  639. m_nTimeHistoryPos = (m_nTimeHistoryPos + 1) % 64;
  640. */
  641. // limit fps, if necessary
  642. /*
  643. if (m_nFpsLimit > 0 && (GetFrame() % 64) == 0 && GetFrame() > 64)
  644. {
  645. float spf_now = 1.0f / m_fps;
  646. float spf_desired = 1.0f / (float)m_nFpsLimit;
  647. float new_sleep = m_fFPSLimitSleep + (spf_desired - spf_now)*1000.0f;
  648. if (GetFrame() <= 128)
  649. m_fFPSLimitSleep = new_sleep;
  650. else
  651. m_fFPSLimitSleep = m_fFPSLimitSleep*0.8f + 0.2f*new_sleep;
  652. if (m_fFPSLimitSleep < 0) m_fFPSLimitSleep = 0;
  653. if (m_fFPSLimitSleep > 100) m_fFPSLimitSleep = 100;
  654. //sprintf(m_szUserMessage, "sleep=%f", m_fFPSLimitSleep);
  655. //m_fShowUserMessageUntilThisTime = GetTime() + 3.0f;
  656. }
  657. static float deficit;
  658. if (GetFrame()==0) deficit = 0;
  659. float ideal_sleep = (m_fFPSLimitSleep + deficit);
  660. int actual_sleep = (int)ideal_sleep;
  661. if (actual_sleep > 0)
  662. Sleep(actual_sleep);
  663. deficit = ideal_sleep - actual_sleep;
  664. if (deficit < 0) deficit = 0; // just in case
  665. if (deficit > 1) deficit = 1; // just in case
  666. */
  667. // randomly change the preset, if it's time
  668. if (m_fNextPresetTime < GetTime())
  669. {
  670. LoadRandomPreset(m_fBlendTimeAuto);
  671. }
  672. /*
  673. // randomly spawn Song Title, if time
  674. if (m_fTimeBetweenRandomSongTitles > 0 &&
  675. !m_supertext.bRedrawSuperText &&
  676. GetTime() >= m_supertext.fStartTime + m_supertext.fDuration + 1.0f/GetFps())
  677. {
  678. int n = GetNumToSpawn(GetTime(), fDeltaT, 1.0f/m_fTimeBetweenRandomSongTitles, 0.5f, m_nSongTitlesSpawned);
  679. if (n > 0)
  680. {
  681. LaunchSongTitleAnim();
  682. m_nSongTitlesSpawned += n;
  683. }
  684. }
  685. // randomly spawn Custom Message, if time
  686. if (m_fTimeBetweenRandomCustomMsgs > 0 &&
  687. !m_supertext.bRedrawSuperText &&
  688. GetTime() >= m_supertext.fStartTime + m_supertext.fDuration + 1.0f/GetFps())
  689. {
  690. int n = GetNumToSpawn(GetTime(), fDeltaT, 1.0f/m_fTimeBetweenRandomCustomMsgs, 0.5f, m_nCustMsgsSpawned);
  691. if (n > 0)
  692. {
  693. LaunchCustomMessage(-1);
  694. m_nCustMsgsSpawned += n;
  695. }
  696. }
  697. */
  698. // update m_fBlendProgress;
  699. if (m_pState->m_bBlending)
  700. {
  701. m_pState->m_fBlendProgress = (GetTime() - m_pState->m_fBlendStartTime) / m_pState->m_fBlendDuration;
  702. if (m_pState->m_fBlendProgress > 1.0f)
  703. {
  704. m_pState->m_bBlending = false;
  705. }
  706. }
  707. // handle hard cuts here (just after new sound analysis)
  708. static float m_fHardCutThresh;
  709. if (GetFrame() == 0)
  710. m_fHardCutThresh = m_fHardCutLoudnessThresh*2.0f;
  711. if (GetFps() > 1.0f && !m_bHardCutsDisabled && !m_bPresetLockedByUser && !m_bPresetLockedByCode)
  712. {
  713. if (mysound.imm_rel[0] + mysound.imm_rel[1] + mysound.imm_rel[2] > m_fHardCutThresh*3.0f)
  714. {
  715. LoadRandomPreset(0.0f);
  716. m_fHardCutThresh *= 2.0f;
  717. }
  718. else
  719. {
  720. float halflife_modified = m_fHardCutHalflife*0.5f;
  721. //thresh = (thresh - 1.5f)*0.99f + 1.5f;
  722. float k = -0.69315f / halflife_modified;
  723. float single_frame_multiplier = powf(2.7183f, k / GetFps());
  724. m_fHardCutThresh = (m_fHardCutThresh - m_fHardCutLoudnessThresh)*single_frame_multiplier + m_fHardCutLoudnessThresh;
  725. }
  726. }
  727. // smooth & scale the audio data, according to m_state, for display purposes
  728. float scale = m_pState->m_fWaveScale.eval(GetTime()) / 128.0f;
  729. mysound.fWave[0][0] *= scale;
  730. mysound.fWave[1][0] *= scale;
  731. float mix2 = m_pState->m_fWaveSmoothing.eval(GetTime());
  732. float mix1 = scale*(1.0f - mix2);
  733. for (i=1; i<576; i++)
  734. {
  735. mysound.fWave[0][i] = mysound.fWave[0][i]*mix1 + mysound.fWave[0][i-1]*mix2;
  736. mysound.fWave[1][i] = mysound.fWave[1][i]*mix1 + mysound.fWave[1][i-1]*mix2;
  737. }
  738. RunPerFrameEquations();
  739. // restore any lost surfaces
  740. //m_lpDD->RestoreAllSurfaces();
  741. LPDIRECT3DDEVICE9 lpDevice = GetDevice();
  742. if (!lpDevice)
  743. return;
  744. // Remember the original backbuffer and zbuffer
  745. LPDIRECT3DSURFACE9 pBackBuffer, pZBuffer;
  746. lpDevice->GetRenderTarget(0, &pBackBuffer );
  747. lpDevice->GetDepthStencilSurface( &pZBuffer );
  748. D3DSURFACE_DESC desc;
  749. pBackBuffer->GetDesc(&desc);
  750. m_backBufferWidth = desc.Width;
  751. m_backBufferHeight = desc.Height;
  752. // set up render state
  753. {
  754. DWORD texaddr = (*m_pState->var_pf_wrap) ? D3DTADDRESS_WRAP : D3DTADDRESS_CLAMP;
  755. lpDevice->SetRenderState(D3DRS_WRAP0, 0);
  756. lpDevice->SetSamplerState(0, D3DSAMP_ADDRESSU, texaddr);
  757. lpDevice->SetSamplerState(0, D3DSAMP_ADDRESSV, texaddr);
  758. lpDevice->SetSamplerState(0, D3DSAMP_ADDRESSW, texaddr);
  759. lpDevice->SetRenderState( D3DRS_SHADEMODE, D3DSHADE_GOURAUD );
  760. lpDevice->SetRenderState( D3DRS_SPECULARENABLE, FALSE );
  761. lpDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );
  762. lpDevice->SetRenderState( D3DRS_ZENABLE, FALSE );
  763. lpDevice->SetRenderState( D3DRS_ZWRITEENABLE, FALSE );
  764. lpDevice->SetRenderState( D3DRS_LIGHTING, FALSE );
  765. lpDevice->SetRenderState( D3DRS_COLORVERTEX, TRUE );
  766. lpDevice->SetRenderState( D3DRS_FILLMODE, D3DFILL_SOLID );
  767. lpDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE );
  768. lpDevice->SetRenderState( D3DRS_AMBIENT, 0xFFFFFFFF ); //?
  769. // lpDevice->SetRenderState( D3DRS_CLIPPING, TRUE );
  770. // set min/mag/mip filtering modes; use anisotropy if available.
  771. if (m_bAnisotropicFiltering && (GetCaps()->TextureFilterCaps & D3DPTFILTERCAPS_MAGFANISOTROPIC))
  772. lpDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_ANISOTROPIC);
  773. // else if (GetCaps()->TextureFilterCaps & D3DPTFILTERCAPS_MAGFLINEAR)
  774. else
  775. lpDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
  776. // else
  777. // SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTEXF_POINT);
  778. if (m_bAnisotropicFiltering && (GetCaps()->TextureFilterCaps & D3DPTFILTERCAPS_MINFANISOTROPIC))
  779. lpDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_ANISOTROPIC);
  780. else
  781. // else if (GetCaps()->TextureFilterCaps & D3DPTFILTERCAPS_MINFLINEAR)
  782. lpDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
  783. // else
  784. // SetTextureStageState(0, D3DTSS_MINFILTER, D3DTEXF_LINEAR);
  785. lpDevice->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR );
  786. // note: this texture stage state setup works for 0 or 1 texture.
  787. // if you set a texture, it will be modulated with the current diffuse color.
  788. // if you don't set a texture, it will just use the current diffuse color.
  789. lpDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
  790. lpDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_DIFFUSE);
  791. lpDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_TEXTURE);
  792. lpDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
  793. lpDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );
  794. lpDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE );
  795. lpDevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
  796. if (GetCaps()->RasterCaps & D3DPRASTERCAPS_DITHER)
  797. lpDevice->SetRenderState(D3DRS_DITHERENABLE, FALSE);
  798. /* WISO: if (GetCaps()->RasterCaps & D3DPRASTERCAPS_ANTIALIASEDGES)
  799. lpDevice->SetRenderState(D3DRS_MULTISAMPLEANTIALIAS, TRUE);*/
  800. // NOTE: don't forget to call SetTexture and SetVertexShader before drawing!
  801. // Examples:
  802. // SPRITEVERTEX verts[4]; // has texcoords
  803. // lpDevice->SetTexture(0, m_sprite_tex);
  804. // lpDevice->SetVertexShader( SPRITEVERTEX_FORMAT );
  805. //
  806. // WFVERTEX verts[4]; // no texcoords
  807. // lpDevice->SetTexture(0, NULL);
  808. // lpDevice->SetVertexShader( WFVERTEX_FORMAT );
  809. }
  810. // render string to m_lpDDSTitle, if necessary
  811. if (m_supertext.bRedrawSuperText)
  812. {
  813. if (!RenderStringToTitleTexture())
  814. m_supertext.fStartTime = -1.0f;
  815. m_supertext.bRedrawSuperText = false;
  816. }
  817. // set up to render [from NULL] to VS0 (for motion vectors).
  818. {
  819. lpDevice->SetTexture(0, NULL);
  820. IDirect3DSurface9* pNewTarget = NULL;
  821. if (m_lpVS[0]->GetSurfaceLevel(0, &pNewTarget) != D3D_OK)
  822. return;
  823. lpDevice->SetRenderTarget(0, pNewTarget);
  824. pNewTarget->Release();
  825. lpDevice->SetDepthStencilSurface( NULL );
  826. lpDevice->SetTexture(0, NULL);
  827. }
  828. // draw motion vectors to VS0
  829. DrawMotionVectors();
  830. // set up to render [from VS0] to VS1.
  831. {
  832. lpDevice->SetTexture(0, NULL);
  833. IDirect3DSurface9* pNewTarget = NULL;
  834. if (m_lpVS[1]->GetSurfaceLevel(0, &pNewTarget) != D3D_OK)
  835. return;
  836. lpDevice->SetRenderTarget(0, pNewTarget);
  837. lpDevice->SetDepthStencilSurface( NULL );
  838. pNewTarget->Release();
  839. }
  840. // do the warping for this frame
  841. if (GetCaps()->RasterCaps & D3DPRASTERCAPS_DITHER)
  842. lpDevice->SetRenderState(D3DRS_DITHERENABLE, TRUE);
  843. /* WISO: if (GetCaps()->RasterCaps & D3DPRASTERCAPS_ANTIALIASEDGES)
  844. lpDevice->SetRenderState(D3DRS_EDGEANTIALIAS, FALSE);*/
  845. WarpedBlitFromVS0ToVS1();
  846. if (GetCaps()->RasterCaps & D3DPRASTERCAPS_DITHER)
  847. lpDevice->SetRenderState(D3DRS_DITHERENABLE, FALSE);
  848. /*if (GetCaps()->RasterCaps & D3DPRASTERCAPS_ANTIALIASEDGES)
  849. lpDevice->SetRenderState(D3DRS_EDGEANTIALIAS, TRUE);*/
  850. // draw audio data
  851. DrawCustomShapes(); // draw these first; better for feedback if the waves draw *over* them.
  852. DrawCustomWaves();
  853. DrawWave(mysound.fWave[0], mysound.fWave[1]);
  854. DrawSprites();
  855. // if song title animation just ended, render it into the VS:
  856. if (m_supertext.fStartTime >= 0 &&
  857. GetTime() >= m_supertext.fStartTime + m_supertext.fDuration &&
  858. !m_supertext.bRedrawSuperText)
  859. {
  860. m_supertext.fStartTime = -1.0f; // 'off' state
  861. ShowSongTitleAnim(m_nTexSize, m_nTexSize, 1.0f);
  862. }
  863. // Change the rendertarget back to the original setup
  864. lpDevice->SetTexture(0, NULL);
  865. // WISO: lpDevice->SetRenderTarget( pBackBuffer, pZBuffer );
  866. lpDevice->SetRenderTarget(0, pBackBuffer);
  867. lpDevice->SetDepthStencilSurface( pZBuffer );
  868. SafeRelease(pBackBuffer);
  869. SafeRelease(pZBuffer);
  870. /* WISO: if (GetCaps()->RasterCaps & D3DPRASTERCAPS_ANTIALIASEDGES)
  871. lpDevice->SetRenderState(D3DRS_EDGEANTIALIAS, FALSE);*/
  872. // show it to user
  873. ShowToUser(bRedraw);
  874. // finally, render song title animation to back buffer
  875. if (m_supertext.fStartTime >= 0 &&
  876. GetTime() < m_supertext.fStartTime + m_supertext.fDuration &&
  877. !m_supertext.bRedrawSuperText)
  878. {
  879. float fProgress = (GetTime() - m_supertext.fStartTime) / m_supertext.fDuration;
  880. ShowSongTitleAnim(GetWidth(), GetHeight(), fProgress);
  881. }
  882. DrawUserSprites();
  883. // flip buffers
  884. IDirect3DTexture9* pTemp = m_lpVS[0];
  885. m_lpVS[0] = m_lpVS[1];
  886. m_lpVS[1] = pTemp;
  887. /* WISO: if (GetCaps()->RasterCaps & D3DPRASTERCAPS_ANTIALIASEDGES)
  888. lpDevice->SetRenderState(D3DRS_EDGEANTIALIAS, FALSE);*/
  889. if (GetCaps()->RasterCaps & D3DPRASTERCAPS_DITHER)
  890. lpDevice->SetRenderState(D3DRS_DITHERENABLE, FALSE);
  891. }
  892. void CPlugin::DrawMotionVectors()
  893. {
  894. // FLEXIBLE MOTION VECTOR FIELD
  895. if ((float)*m_pState->var_pf_mv_a >= 0.001f)
  896. {
  897. //-------------------------------------------------------
  898. LPDIRECT3DDEVICE9 lpDevice = GetDevice();
  899. if (!lpDevice)
  900. return;
  901. lpDevice->SetTexture(0, NULL);
  902. lpDevice->SetFVF(WFVERTEX_FORMAT);
  903. //-------------------------------------------------------
  904. int x,y;
  905. int nX = (int)(*m_pState->var_pf_mv_x);// + 0.999f);
  906. int nY = (int)(*m_pState->var_pf_mv_y);// + 0.999f);
  907. float dx = (float)*m_pState->var_pf_mv_x - nX;
  908. float dy = (float)*m_pState->var_pf_mv_y - nY;
  909. if (nX > 64) { nX = 64; dx = 0; }
  910. if (nY > 48) { nY = 48; dy = 0; }
  911. if (nX > 0 && nY > 0)
  912. {
  913. /*
  914. float dx2 = m_fMotionVectorsTempDx;//(*m_pState->var_pf_mv_dx) * 0.05f*GetTime(); // 0..1 range
  915. float dy2 = m_fMotionVectorsTempDy;//(*m_pState->var_pf_mv_dy) * 0.05f*GetTime(); // 0..1 range
  916. if (GetFps() > 2.0f && GetFps() < 300.0f)
  917. {
  918. dx2 += (float)(*m_pState->var_pf_mv_dx) * 0.05f / GetFps();
  919. dy2 += (float)(*m_pState->var_pf_mv_dy) * 0.05f / GetFps();
  920. }
  921. if (dx2 > 1.0f) dx2 -= (int)dx2;
  922. if (dy2 > 1.0f) dy2 -= (int)dy2;
  923. if (dx2 < 0.0f) dx2 = 1.0f - (-dx2 - (int)(-dx2));
  924. if (dy2 < 0.0f) dy2 = 1.0f - (-dy2 - (int)(-dy2));
  925. // hack: when there is only 1 motion vector on the screem, to keep it in
  926. // the center, we gradually migrate it toward 0.5.
  927. dx2 = dx2*0.995f + 0.5f*0.005f;
  928. dy2 = dy2*0.995f + 0.5f*0.005f;
  929. // safety catch
  930. if (dx2 < 0 || dx2 > 1 || dy2 < 0 || dy2 > 1)
  931. {
  932. dx2 = 0.5f;
  933. dy2 = 0.5f;
  934. }
  935. m_fMotionVectorsTempDx = dx2;
  936. m_fMotionVectorsTempDy = dy2;*/
  937. float dx2 = (float)(*m_pState->var_pf_mv_dx);
  938. float dy2 = (float)(*m_pState->var_pf_mv_dy);
  939. float len_mult = (float)*m_pState->var_pf_mv_l;
  940. if (dx < 0) dx = 0;
  941. if (dy < 0) dy = 0;
  942. if (dx > 1) dx = 1;
  943. if (dy > 1) dy = 1;
  944. //dx = dx * 1.0f/(float)nX;
  945. //dy = dy * 1.0f/(float)nY;
  946. float inv_texsize = 1.0f/(float)m_nTexSize;
  947. float min_len = 1.0f*inv_texsize;
  948. WFVERTEX v[(64+1)*2];
  949. ZeroMemory(v, sizeof(WFVERTEX)*(64+1)*2);
  950. v[0].Diffuse = D3DCOLOR_RGBA_01((float)*m_pState->var_pf_mv_r,(float)*m_pState->var_pf_mv_g,(float)*m_pState->var_pf_mv_b,(float)*m_pState->var_pf_mv_a);
  951. for (x=1; x<(nX+1)*2; x++)
  952. v[x].Diffuse = v[0].Diffuse;
  953. lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
  954. lpDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
  955. lpDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
  956. for (y=0; y<nY; y++)
  957. {
  958. float fy = (y + 0.25f)/(float)(nY + dy + 0.25f - 1.0f);
  959. // now move by offset
  960. fy -= dy2;
  961. if (fy > 0.0001f && fy < 0.9999f)
  962. {
  963. int n = 0;
  964. for (x=0; x<nX; x++)
  965. {
  966. //float fx = (x + 0.25f)/(float)(nX + dx + 0.25f - 1.0f);
  967. float fx = (x + 0.25f)/(float)(nX + dx + 0.25f - 1.0f);
  968. // now move by offset
  969. fx += dx2;
  970. if (fx > 0.0001f && fx < 0.9999f)
  971. {
  972. float fx2, fy2;
  973. ReversePropagatePoint(fx, fy, &fx2, &fy2); // NOTE: THIS IS REALLY A REVERSE-PROPAGATION
  974. //fx2 = fx*2 - fx2;
  975. //fy2 = fy*2 - fy2;
  976. //fx2 = fx + 1.0f/(float)m_nTexSize;
  977. //fy2 = 1-(fy + 1.0f/(float)m_nTexSize);
  978. // enforce minimum trail lengths:
  979. {
  980. float dx = (fx2 - fx);
  981. float dy = (fy2 - fy);
  982. dx *= len_mult;
  983. dy *= len_mult;
  984. float len = sqrtf(dx*dx + dy*dy);
  985. if (len > min_len)
  986. {
  987. }
  988. else if (len > 0.00000001f)
  989. {
  990. len = min_len/len;
  991. dx *= len;
  992. dy *= len;
  993. }
  994. else
  995. {
  996. dx = min_len;
  997. dy = min_len;
  998. }
  999. fx2 = fx + dx;
  1000. fy2 = fy + dy;
  1001. }
  1002. /**/
  1003. v[n].x = fx * 2.0f - 1.0f;
  1004. v[n].y = fy * 2.0f - 1.0f;
  1005. v[n+1].x = fx2 * 2.0f - 1.0f;
  1006. v[n+1].y = fy2 * 2.0f - 1.0f;
  1007. // actually, project it in the reverse direction
  1008. //v[n+1].x = v[n].x*2.0f - v[n+1].x;// + dx*2;
  1009. //v[n+1].y = v[n].y*2.0f - v[n+1].y;// + dy*2;
  1010. //v[n].x += dx*2;
  1011. //v[n].y += dy*2;
  1012. n += 2;
  1013. }
  1014. }
  1015. // draw it
  1016. if (n != 0)
  1017. lpDevice->DrawPrimitiveUP(D3DPT_LINELIST, n/2, v, sizeof(WFVERTEX));
  1018. }
  1019. }
  1020. lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
  1021. }
  1022. }
  1023. }
  1024. /*
  1025. void CPlugin::UpdateSongInfo()
  1026. {
  1027. if (m_bShowSongTitle || m_bSongTitleAnims)
  1028. {
  1029. char szOldSongMessage[512];
  1030. strcpy(szOldSongMessage, m_szSongMessage);
  1031. if (::GetWindowText(m_hWndParent, m_szSongMessage, sizeof(m_szSongMessage)))
  1032. {
  1033. // remove ' - Winamp' at end
  1034. if (strlen(m_szSongMessage) > 9)
  1035. {
  1036. int check_pos = strlen(m_szSongMessage) - 9;
  1037. if (strcmp(" - Winamp", (char *)(m_szSongMessage + check_pos)) == 0)
  1038. m_szSongMessage[check_pos] = 0;
  1039. }
  1040. // remove ' - Winamp [Paused]' at end
  1041. if (strlen(m_szSongMessage) > 18)
  1042. {
  1043. int check_pos = strlen(m_szSongMessage) - 18;
  1044. if (strcmp(" - Winamp [Paused]", (char *)(m_szSongMessage + check_pos)) == 0)
  1045. m_szSongMessage[check_pos] = 0;
  1046. }
  1047. // remove song # and period from beginning
  1048. char *p = m_szSongMessage;
  1049. while (*p >= '0' && *p <= '9') p++;
  1050. if (*p == '.' && *(p+1) == ' ')
  1051. {
  1052. p += 2;
  1053. int pos = 0;
  1054. while (*p != 0)
  1055. {
  1056. m_szSongMessage[pos++] = *p;
  1057. p++;
  1058. }
  1059. m_szSongMessage[pos++] = 0;
  1060. }
  1061. // fix &'s for display
  1062. /*
  1063. {
  1064. int pos = 0;
  1065. int len = strlen(m_szSongMessage);
  1066. while (m_szSongMessage[pos])
  1067. {
  1068. if (m_szSongMessage[pos] == '&')
  1069. {
  1070. for (int x=len; x>=pos; x--)
  1071. m_szSongMessage[x+1] = m_szSongMessage[x];
  1072. len++;
  1073. pos++;
  1074. }
  1075. pos++;
  1076. }
  1077. }*/
  1078. /*
  1079. if (m_bSongTitleAnims &&
  1080. ((strcmp(szOldSongMessage, m_szSongMessage) != 0) || (GetFrame()==0)))
  1081. {
  1082. // launch song title animation
  1083. LaunchSongTitleAnim();
  1084. /*
  1085. m_supertext.bRedrawSuperText = true;
  1086. m_supertext.bIsSongTitle = true;
  1087. strcpy(m_supertext.szText, m_szSongMessage);
  1088. strcpy(m_supertext.nFontFace, m_szTitleFontFace);
  1089. m_supertext.fFontSize = (float)m_nTitleFontSize;
  1090. m_supertext.bBold = m_bTitleFontBold;
  1091. m_supertext.bItal = m_bTitleFontItalic;
  1092. m_supertext.fX = 0.5f;
  1093. m_supertext.fY = 0.5f;
  1094. m_supertext.fGrowth = 1.0f;
  1095. m_supertext.fDuration = m_fSongTitleAnimDuration;
  1096. m_supertext.nColorR = 255;
  1097. m_supertext.nColorG = 255;
  1098. m_supertext.nColorB = 255;
  1099. m_supertext.fStartTime = GetTime();
  1100. */
  1101. /* }
  1102. }
  1103. else
  1104. {
  1105. sprintf(m_szSongMessage, "<couldn't get song title>");
  1106. }
  1107. }
  1108. m_nTrackPlaying = SendMessage(m_hWndParent,WM_USER, 0, 125);
  1109. // append song time
  1110. if (m_bShowSongTime && m_nSongPosMS >= 0)
  1111. {
  1112. float time_s = m_nSongPosMS*0.001f;
  1113. int minutes = (int)(time_s/60);
  1114. time_s -= minutes*60;
  1115. int seconds = (int)time_s;
  1116. time_s -= seconds;
  1117. int dsec = (int)(time_s*100);
  1118. sprintf(m_szSongTime, "%d:%02d.%02d", minutes, seconds, dsec);
  1119. }
  1120. // append song length
  1121. if (m_bShowSongLen && m_nSongLenMS > 0)
  1122. {
  1123. int len_s = m_nSongLenMS/1000;
  1124. int minutes = len_s/60;
  1125. int seconds = len_s - minutes*60;
  1126. char buf[512];
  1127. sprintf(buf, " / %d:%02d", minutes, seconds);
  1128. strcat(m_szSongTime, buf);
  1129. }
  1130. }
  1131. */
  1132. bool CPlugin::ReversePropagatePoint(float fx, float fy, float *fx2, float *fy2)
  1133. {
  1134. //float fy = y/(float)nMotionVectorsY;
  1135. int y0 = (int)(fy*m_nGridY);
  1136. float dy = fy*m_nGridY - y0;
  1137. //float fx = x/(float)nMotionVectorsX;
  1138. int x0 = (int)(fx*m_nGridX);
  1139. float dx = fx*m_nGridX - x0;
  1140. int x1 = x0 + 1;
  1141. int y1 = y0 + 1;
  1142. if (x0 < 0) return false;
  1143. if (y0 < 0) return false;
  1144. //if (x1 < 0) return false;
  1145. //if (y1 < 0) return false;
  1146. //if (x0 > m_nGridX) return false;
  1147. //if (y0 > m_nGridY) return false;
  1148. if (x1 > m_nGridX) return false;
  1149. if (y1 > m_nGridY) return false;
  1150. float tu, tv;
  1151. tu = m_verts[y0*(m_nGridX+1)+x0].tu * (1-dx)*(1-dy);
  1152. tv = m_verts[y0*(m_nGridX+1)+x0].tv * (1-dx)*(1-dy);
  1153. tu += m_verts[y0*(m_nGridX+1)+x1].tu * (dx)*(1-dy);
  1154. tv += m_verts[y0*(m_nGridX+1)+x1].tv * (dx)*(1-dy);
  1155. tu += m_verts[y1*(m_nGridX+1)+x0].tu * (1-dx)*(dy);
  1156. tv += m_verts[y1*(m_nGridX+1)+x0].tv * (1-dx)*(dy);
  1157. tu += m_verts[y1*(m_nGridX+1)+x1].tu * (dx)*(dy);
  1158. tv += m_verts[y1*(m_nGridX+1)+x1].tv * (dx)*(dy);
  1159. *fx2 = tu;
  1160. *fy2 = 1.0f - tv;
  1161. return true;
  1162. }
  1163. void CPlugin::WarpedBlitFromVS0ToVS1()
  1164. {
  1165. MungeFPCW(NULL); // puts us in single-precision mode & disables exceptions
  1166. LPDIRECT3DDEVICE9 lpDevice = GetDevice();
  1167. if (!lpDevice)
  1168. return;
  1169. lpDevice->SetTexture(0, m_lpVS[0]);
  1170. lpDevice->SetFVF( SPRITEVERTEX_FORMAT );
  1171. // warp stuff
  1172. float fWarpTime = GetTime() * m_pState->m_fWarpAnimSpeed;
  1173. float fWarpScale = m_pState->m_fWarpScale.eval(GetTime());
  1174. float fWarpScaleInv = 1.0f;
  1175. if(fWarpScale != 0.0f)
  1176. fWarpScaleInv = 1.0f / fWarpScale;
  1177. float f[4];
  1178. f[0] = 11.68f + 4.0f*cosf(fWarpTime*1.413f + 10);
  1179. f[1] = 8.77f + 3.0f*cosf(fWarpTime*1.113f + 7);
  1180. f[2] = 10.54f + 3.0f*cosf(fWarpTime*1.233f + 3);
  1181. f[3] = 11.49f + 4.0f*cosf(fWarpTime*0.933f + 5);
  1182. int num_reps = (m_pState->m_bBlending) ? 2 : 1;
  1183. float fCosineBlend = 0.50f*(m_pState->m_fBlendProgress) + 0.50f*CosineInterp(m_pState->m_fBlendProgress);
  1184. float fCosineBlend2 = 0.40f*(m_pState->m_fBlendProgress) + 0.60f*CosineInterp(m_pState->m_fBlendProgress);
  1185. // decay
  1186. float fDecay = (float)(*m_pState->var_pf_decay);
  1187. // texel alignment
  1188. float texel_offset = 0.5f / (float)m_nTexSize;
  1189. //if (m_pState->m_bBlending)
  1190. // fDecay = fDecay*(fCosineBlend) + (1.0f-fCosineBlend)*((float)(*m_pOldState->var_pf_decay));
  1191. if (m_bAutoGamma && GetFrame()==0)
  1192. {
  1193. if (strstr(GetDriverDescription(), "nvidia") ||
  1194. strstr(GetDriverDescription(), "nVidia") ||
  1195. strstr(GetDriverDescription(), "NVidia") ||
  1196. strstr(GetDriverDescription(), "NVIDIA"))
  1197. m_n16BitGamma = 2;
  1198. else if (strstr(GetDriverDescription(), "ATI RAGE MOBILITY M"))
  1199. m_n16BitGamma = 2;
  1200. else
  1201. m_n16BitGamma = 0;
  1202. }
  1203. if (m_n16BitGamma > 0 &&
  1204. (GetBackBufFormat()==D3DFMT_R5G6B5 || GetBackBufFormat()==D3DFMT_X1R5G5B5 || GetBackBufFormat()==D3DFMT_A1R5G5B5 || GetBackBufFormat()==D3DFMT_A4R4G4B4) &&
  1205. fDecay < 0.9999f)
  1206. {
  1207. fDecay = min(fDecay, (32.0f - m_n16BitGamma)/32.0f);
  1208. }
  1209. D3DCOLOR cDecay = D3DCOLOR_RGBA_01(fDecay,fDecay,fDecay,1);
  1210. for (int rep=0; rep<num_reps; rep++)
  1211. {
  1212. CState *pState;
  1213. if (rep==0)
  1214. pState = m_pState;
  1215. else
  1216. pState = m_pOldState;
  1217. resetVars(pState->m_pv_vars);
  1218. // cache the doubles as floats so that computations are a bit faster
  1219. float fZoom = (float)(*pState->var_pf_zoom);
  1220. float fZoomExp = (float)(*pState->var_pf_zoomexp);
  1221. float fRot = (float)(*pState->var_pf_rot);
  1222. float fWarp = (float)(*pState->var_pf_warp);
  1223. float fCX = (float)(*pState->var_pf_cx);
  1224. float fCY = (float)(*pState->var_pf_cy);
  1225. float fDX = (float)(*pState->var_pf_dx);
  1226. float fDY = (float)(*pState->var_pf_dy);
  1227. float fSX = (float)(*pState->var_pf_sx);
  1228. float fSY = (float)(*pState->var_pf_sy);
  1229. int n = 0;
  1230. for (int y=0; y<=m_nGridY; y++)
  1231. {
  1232. for (int x=0; x<=m_nGridX; x++)
  1233. {
  1234. // Note: x, y, z are now set at init. time - no need to mess with them!
  1235. //m_verts[n].x = i/(float)m_nGridX*2.0f - 1.0f;
  1236. //m_verts[n].y = j/(float)m_nGridY*2.0f - 1.0f;
  1237. //m_verts[n].z = 0.0f;
  1238. if (pState->m_pp_codehandle)
  1239. {
  1240. // restore all the variables to their original states,
  1241. // run the user-defined equations,
  1242. // then move the results into local vars for computation as floats
  1243. *pState->var_pv_x = (double)(m_verts[n].x*0.5f + 0.5f);
  1244. *pState->var_pv_y = (double)(m_verts[n].y*-0.5f + 0.5f);
  1245. *pState->var_pv_rad = (double)m_vertinfo[n].rad;
  1246. *pState->var_pv_ang = (double)m_vertinfo[n].ang;
  1247. *pState->var_pv_zoom = *pState->var_pf_zoom;
  1248. *pState->var_pv_zoomexp = *pState->var_pf_zoomexp;
  1249. *pState->var_pv_rot = *pState->var_pf_rot;
  1250. *pState->var_pv_warp = *pState->var_pf_warp;
  1251. *pState->var_pv_cx = *pState->var_pf_cx;
  1252. *pState->var_pv_cy = *pState->var_pf_cy;
  1253. *pState->var_pv_dx = *pState->var_pf_dx;
  1254. *pState->var_pv_dy = *pState->var_pf_dy;
  1255. *pState->var_pv_sx = *pState->var_pf_sx;
  1256. *pState->var_pv_sy = *pState->var_pf_sy;
  1257. /*
  1258. *pState->var_pv_q1 = *pState->var_pf_q1;
  1259. *pState->var_pv_q2 = *pState->var_pf_q2;
  1260. *pState->var_pv_q3 = *pState->var_pf_q3;
  1261. *pState->var_pv_q4 = *pState->var_pf_q4;
  1262. *pState->var_pv_q5 = *pState->var_pf_q5;
  1263. *pState->var_pv_q6 = *pState->var_pf_q6;
  1264. *pState->var_pv_q7 = *pState->var_pf_q7;
  1265. *pState->var_pv_q8 = *pState->var_pf_q8;
  1266. */
  1267. //*pState->var_pv_time = *pState->var_pv_time; // (these are all now initialized
  1268. //*pState->var_pv_bass = *pState->var_pv_bass; // just once per frame)
  1269. //*pState->var_pv_mid = *pState->var_pv_mid;
  1270. //*pState->var_pv_treb = *pState->var_pv_treb;
  1271. //*pState->var_pv_bass_att = *pState->var_pv_bass_att;
  1272. //*pState->var_pv_mid_att = *pState->var_pv_mid_att;
  1273. //*pState->var_pv_treb_att = *pState->var_pv_treb_att;
  1274. #ifndef _NO_EXPR_
  1275. executeCode(pState->m_pp_codehandle);
  1276. #endif
  1277. fZoom = (float)(*pState->var_pv_zoom);
  1278. fZoomExp = (float)(*pState->var_pv_zoomexp);
  1279. fRot = (float)(*pState->var_pv_rot);
  1280. fWarp = (float)(*pState->var_pv_warp);
  1281. fCX = (float)(*pState->var_pv_cx);
  1282. fCY = (float)(*pState->var_pv_cy);
  1283. fDX = (float)(*pState->var_pv_dx);
  1284. fDY = (float)(*pState->var_pv_dy);
  1285. fSX = (float)(*pState->var_pv_sx);
  1286. fSY = (float)(*pState->var_pv_sy);
  1287. }
  1288. float fZoom2 = powf(fZoom, powf(fZoomExp, m_vertinfo[n].rad*2.0f - 1.0f));
  1289. // initial texcoords, w/built-in zoom factor
  1290. float fZoom2Inv = 1.0f/fZoom2;
  1291. float u = m_verts[n].x*0.5f*fZoom2Inv + 0.5f;
  1292. float v = -m_verts[n].y*0.5f*fZoom2Inv + 0.5f;
  1293. // stretch on X, Y:
  1294. u = (u - fCX)/fSX + fCX;
  1295. v = (v - fCY)/fSY + fCY;
  1296. // warping:
  1297. //if (fWarp > 0.001f || fWarp < -0.001f)
  1298. //{
  1299. u += fWarp*0.0035f*sinf(fWarpTime*0.333f + fWarpScaleInv*(m_verts[n].x*f[0] - m_verts[n].y*f[3]));
  1300. v += fWarp*0.0035f*cosf(fWarpTime*0.375f - fWarpScaleInv*(m_verts[n].x*f[2] + m_verts[n].y*f[1]));
  1301. u += fWarp*0.0035f*cosf(fWarpTime*0.753f - fWarpScaleInv*(m_verts[n].x*f[1] - m_verts[n].y*f[2]));
  1302. v += fWarp*0.0035f*sinf(fWarpTime*0.825f + fWarpScaleInv*(m_verts[n].x*f[0] + m_verts[n].y*f[3]));
  1303. //}
  1304. // rotation:
  1305. float u2 = u - fCX;
  1306. float v2 = v - fCY;
  1307. float cos_rot = cosf(fRot);
  1308. float sin_rot = sinf(fRot);
  1309. u = u2*cos_rot - v2*sin_rot + fCX;
  1310. v = u2*sin_rot + v2*cos_rot + fCY;
  1311. // translation:
  1312. u -= fDX - texel_offset;
  1313. v -= fDY - texel_offset;
  1314. if (rep==0)
  1315. {
  1316. //m_verts[n].Diffuse = cDecay; // see below
  1317. m_verts[n].tu = u;
  1318. m_verts[n].tv = v;
  1319. }
  1320. else
  1321. {
  1322. float mix2 = m_vertinfo[n].a*m_pState->m_fBlendProgress + m_vertinfo[n].c;//fCosineBlend2;
  1323. mix2 = max(0,min(1,mix2));
  1324. m_verts[n].tu = m_verts[n].tu*(mix2) + u*(1-mix2);
  1325. m_verts[n].tv = m_verts[n].tv*(mix2) + v*(1-mix2);
  1326. }
  1327. /*
  1328. if (rep==num_reps-1)
  1329. {
  1330. m_verts[n].tu += 0.25f*(FRAND*2-1)/(float)m_nTexSize;
  1331. m_verts[n].tv += 0.25f*(FRAND*2-1)/(float)m_nTexSize;
  1332. }
  1333. */
  1334. n++;
  1335. }
  1336. }
  1337. /*
  1338. pState->q_values_after_init_code[0] = *pState->var_pv_q1;
  1339. pState->q_values_after_init_code[1] = *pState->var_pv_q2;
  1340. pState->q_values_after_init_code[2] = *pState->var_pv_q3;
  1341. pState->q_values_after_init_code[3] = *pState->var_pv_q4;
  1342. pState->q_values_after_init_code[4] = *pState->var_pv_q5;
  1343. pState->q_values_after_init_code[5] = *pState->var_pv_q6;
  1344. pState->q_values_after_init_code[6] = *pState->var_pv_q7;
  1345. pState->q_values_after_init_code[7] = *pState->var_pv_q8;
  1346. */
  1347. resetVars(NULL);
  1348. }
  1349. // hurl the triangle strips at the video card
  1350. int poly;
  1351. for (poly=0; poly<m_nGridX+2; poly++)
  1352. {
  1353. m_verts_temp[poly].Diffuse = cDecay;
  1354. }
  1355. for (int strip=0; strip<m_nGridY*2; strip++)
  1356. {
  1357. int index = strip * (m_nGridX+2);
  1358. for (poly=0; poly<m_nGridX+2; poly++)
  1359. {
  1360. int ref_vert = m_indices[index];
  1361. m_verts_temp[poly].x = m_verts[ref_vert].x;
  1362. m_verts_temp[poly].y = -m_verts[ref_vert].y;
  1363. m_verts_temp[poly].z = m_verts[ref_vert].z;
  1364. m_verts_temp[poly].tu = m_verts[ref_vert].tu;
  1365. m_verts_temp[poly].tv = m_verts[ref_vert].tv;
  1366. //m_verts_temp[poly].Diffuse = 0xFFFFFFFF;
  1367. index++;
  1368. }
  1369. lpDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, m_nGridX, (void*)m_verts_temp, sizeof(SPRITEVERTEX));
  1370. }
  1371. }
  1372. void CPlugin::DrawCustomShapes()
  1373. {
  1374. LPDIRECT3DDEVICE9 lpDevice = GetDevice();
  1375. if (!lpDevice)
  1376. return;
  1377. //lpDevice->SetTexture(0, m_lpVS[0]);//NULL);
  1378. //lpDevice->SetVertexShader( SPRITEVERTEX_FORMAT );
  1379. int num_reps = (m_pState->m_bBlending) ? 2 : 1;
  1380. for (int rep=0; rep<num_reps; rep++)
  1381. {
  1382. CState *pState = (rep==0) ? m_pState : m_pOldState;
  1383. float alpha_mult = 1;
  1384. if (num_reps==2)
  1385. alpha_mult = (rep==0) ? m_pState->m_fBlendProgress : (1-m_pState->m_fBlendProgress);
  1386. for (int i=0; i<MAX_CUSTOM_SHAPES; i++)
  1387. {
  1388. if (pState->m_shape[i].enabled)
  1389. {
  1390. /*
  1391. int bAdditive = 0;
  1392. int nSides = 3;//3 + ((int)GetTime() % 8);
  1393. int bThickOutline = 0;
  1394. float x = 0.5f + 0.1f*cosf(GetTime()*0.8f+1);
  1395. float y = 0.5f + 0.1f*sinf(GetTime()*0.8f+1);
  1396. float rad = 0.15f + 0.07f*sinf(GetTime()*1.1f+3);
  1397. float ang = GetTime()*1.5f;
  1398. // inside colors
  1399. float r = 1;
  1400. float g = 0;
  1401. float b = 0;
  1402. float a = 0.4f;//0.1f + 0.1f*sinf(GetTime()*0.31f);
  1403. // outside colors
  1404. float r2 = 0;
  1405. float g2 = 1;
  1406. float b2 = 0;
  1407. float a2 = 0;
  1408. // border colors
  1409. float border_r = 1;
  1410. float border_g = 1;
  1411. float border_b = 1;
  1412. float border_a = 0.5f;
  1413. */
  1414. // 1. execute per-frame code
  1415. LoadCustomShapePerFrameEvallibVars(pState, i);
  1416. #ifndef _NO_EXPR_
  1417. if (pState->m_shape[i].m_pf_codehandle)
  1418. {
  1419. resetVars(pState->m_shape[i].m_pf_vars);
  1420. executeCode(pState->m_shape[i].m_pf_codehandle);
  1421. resetVars(NULL);
  1422. }
  1423. #endif
  1424. // save changes to t1-t8 this frame
  1425. /*
  1426. pState->m_shape[i].t_values_after_init_code[0] = *pState->m_shape[i].var_pf_t1;
  1427. pState->m_shape[i].t_values_after_init_code[1] = *pState->m_shape[i].var_pf_t2;
  1428. pState->m_shape[i].t_values_after_init_code[2] = *pState->m_shape[i].var_pf_t3;
  1429. pState->m_shape[i].t_values_after_init_code[3] = *pState->m_shape[i].var_pf_t4;
  1430. pState->m_shape[i].t_values_after_init_code[4] = *pState->m_shape[i].var_pf_t5;
  1431. pState->m_shape[i].t_values_after_init_code[5] = *pState->m_shape[i].var_pf_t6;
  1432. pState->m_shape[i].t_values_after_init_code[6] = *pState->m_shape[i].var_pf_t7;
  1433. pState->m_shape[i].t_values_after_init_code[7] = *pState->m_shape[i].var_pf_t8;
  1434. */
  1435. int sides = (int)(*pState->m_shape[i].var_pf_sides);
  1436. if (sides<3) sides=3;
  1437. if (sides>100) sides=100;
  1438. lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
  1439. lpDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
  1440. lpDevice->SetRenderState(D3DRS_DESTBLEND, ((int)(*pState->m_shape[i].var_pf_additive) != 0) ? D3DBLEND_ONE : D3DBLEND_INVSRCALPHA);
  1441. SPRITEVERTEX v[512]; // for textured shapes (has texcoords)
  1442. WFVERTEX v2[512]; // for untextured shapes + borders
  1443. v[0].x = (float)(*pState->m_shape[i].var_pf_x* 2-1);// * ASPECT;
  1444. v[0].y = (float)(*pState->m_shape[i].var_pf_y*-2+1);
  1445. v[0].z = 0;
  1446. v[0].tu = 0.5f;
  1447. v[0].tv = 0.5f;
  1448. v[0].Diffuse =
  1449. ((((int)(*pState->m_shape[i].var_pf_a * 255 * alpha_mult)) & 0xFF) << 24) |
  1450. ((((int)(*pState->m_shape[i].var_pf_r * 255)) & 0xFF) << 16) |
  1451. ((((int)(*pState->m_shape[i].var_pf_g * 255)) & 0xFF) << 8) |
  1452. ((((int)(*pState->m_shape[i].var_pf_b * 255)) & 0xFF) );
  1453. v[1].Diffuse =
  1454. ((((int)(*pState->m_shape[i].var_pf_a2 * 255 * alpha_mult)) & 0xFF) << 24) |
  1455. ((((int)(*pState->m_shape[i].var_pf_r2 * 255)) & 0xFF) << 16) |
  1456. ((((int)(*pState->m_shape[i].var_pf_g2 * 255)) & 0xFF) << 8) |
  1457. ((((int)(*pState->m_shape[i].var_pf_b2 * 255)) & 0xFF) );
  1458. for (int j=1; j<sides+1; j++)
  1459. {
  1460. float t = (j-1)/(float)sides;
  1461. v[j].x = v[0].x + (float)*pState->m_shape[i].var_pf_rad*cosf(t*3.1415927f*2 + (float)*pState->m_shape[i].var_pf_ang + 3.1415927f*0.25f)*ASPECT; // DON'T TOUCH!
  1462. v[j].y = v[0].y + (float)*pState->m_shape[i].var_pf_rad*sinf(t*3.1415927f*2 + (float)*pState->m_shape[i].var_pf_ang + 3.1415927f*0.25f); // DON'T TOUCH!
  1463. v[j].z = 0;
  1464. v[j].tu = 0.5f + 0.5f*cosf(t*3.1415927f*2 + (float)*pState->m_shape[i].var_pf_tex_ang + 3.1415927f*0.25f)/((float)*pState->m_shape[i].var_pf_tex_zoom) * ASPECT; // DON'T TOUCH!
  1465. v[j].tv = 0.5f + 0.5f*sinf(t*3.1415927f*2 + (float)*pState->m_shape[i].var_pf_tex_ang + 3.1415927f*0.25f)/((float)*pState->m_shape[i].var_pf_tex_zoom); // DON'T TOUCH!
  1466. v[j].Diffuse = v[1].Diffuse;
  1467. }
  1468. v[sides+1] = v[1];
  1469. if ((int)(*pState->m_shape[i].var_pf_textured) != 0)
  1470. {
  1471. // draw textured version
  1472. lpDevice->SetTexture(0, m_lpVS[0]);
  1473. lpDevice->SetFVF( SPRITEVERTEX_FORMAT );
  1474. lpDevice->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, sides, (void*)v, sizeof(SPRITEVERTEX));
  1475. }
  1476. else
  1477. {
  1478. // no texture
  1479. for (int j=0; j < sides+2; j++)
  1480. {
  1481. v2[j].x = v[j].x;
  1482. v2[j].y = v[j].y;
  1483. v2[j].z = v[j].z;
  1484. v2[j].Diffuse = v[j].Diffuse;
  1485. }
  1486. lpDevice->SetTexture(0, NULL);
  1487. lpDevice->SetFVF( WFVERTEX_FORMAT );
  1488. lpDevice->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, sides, (void*)v2, sizeof(WFVERTEX));
  1489. }
  1490. // DRAW BORDER
  1491. if (*pState->m_shape[i].var_pf_border_a > 0)
  1492. {
  1493. lpDevice->SetTexture(0, NULL);
  1494. lpDevice->SetFVF( WFVERTEX_FORMAT );
  1495. v2[0].Diffuse =
  1496. ((((int)(*pState->m_shape[i].var_pf_border_a * 255 * alpha_mult)) & 0xFF) << 24) |
  1497. ((((int)(*pState->m_shape[i].var_pf_border_r * 255)) & 0xFF) << 16) |
  1498. ((((int)(*pState->m_shape[i].var_pf_border_g * 255)) & 0xFF) << 8) |
  1499. ((((int)(*pState->m_shape[i].var_pf_border_b * 255)) & 0xFF) );
  1500. for (int j=0; j<sides+2; j++)
  1501. {
  1502. v2[j].x = v[j].x;
  1503. v2[j].y = v[j].y;
  1504. v2[j].z = v[j].z;
  1505. v2[j].Diffuse = v2[0].Diffuse;
  1506. }
  1507. int its = ((int)(*pState->m_shape[i].var_pf_thick) != 0) ? 4 : 1;
  1508. float x_inc = 2.0f / (float)m_nTexSize;
  1509. for (int it=0; it<its; it++)
  1510. {
  1511. switch(it)
  1512. {
  1513. case 0: break;
  1514. case 1: for (int j=0; j<sides+2; j++) v2[j].x += x_inc; break; // draw fat dots
  1515. case 2: for (int j=0; j<sides+2; j++) v2[j].y += x_inc; break; // draw fat dots
  1516. case 3: for (int j=0; j<sides+2; j++) v2[j].x -= x_inc; break; // draw fat dots
  1517. }
  1518. lpDevice->DrawPrimitiveUP(D3DPT_LINESTRIP, sides, (void*)&v2[1], sizeof(WFVERTEX));
  1519. }
  1520. lpDevice->SetTexture(0, m_lpVS[0]);
  1521. lpDevice->SetFVF( SPRITEVERTEX_FORMAT );
  1522. }
  1523. }
  1524. }
  1525. }
  1526. lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
  1527. lpDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
  1528. lpDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
  1529. }
  1530. void CPlugin::LoadCustomShapePerFrameEvallibVars(CState* pState, int i)
  1531. {
  1532. *pState->m_shape[i].var_pf_time = (double)(GetTime() - m_fStartTime);
  1533. *pState->m_shape[i].var_pf_frame = (double)GetFrame();
  1534. *pState->m_shape[i].var_pf_fps = (double)GetFps();
  1535. *pState->m_shape[i].var_pf_progress = (GetTime() - m_fPresetStartTime) / (m_fNextPresetTime - m_fPresetStartTime);
  1536. *pState->m_shape[i].var_pf_bass = (double)mysound.imm_rel[0];
  1537. *pState->m_shape[i].var_pf_mid = (double)mysound.imm_rel[1];
  1538. *pState->m_shape[i].var_pf_treb = (double)mysound.imm_rel[2];
  1539. *pState->m_shape[i].var_pf_bass_att = (double)mysound.avg_rel[0];
  1540. *pState->m_shape[i].var_pf_mid_att = (double)mysound.avg_rel[1];
  1541. *pState->m_shape[i].var_pf_treb_att = (double)mysound.avg_rel[2];
  1542. *pState->m_shape[i].var_pf_q1 = *pState->var_pf_q1;//pState->q_values_after_init_code[0];//0.0f;
  1543. *pState->m_shape[i].var_pf_q2 = *pState->var_pf_q2;//pState->q_values_after_init_code[1];//0.0f;
  1544. *pState->m_shape[i].var_pf_q3 = *pState->var_pf_q3;//pState->q_values_after_init_code[2];//0.0f;
  1545. *pState->m_shape[i].var_pf_q4 = *pState->var_pf_q4;//pState->q_values_after_init_code[3];//0.0f;
  1546. *pState->m_shape[i].var_pf_q5 = *pState->var_pf_q5;//pState->q_values_after_init_code[4];//0.0f;
  1547. *pState->m_shape[i].var_pf_q6 = *pState->var_pf_q6;//pState->q_values_after_init_code[5];//0.0f;
  1548. *pState->m_shape[i].var_pf_q7 = *pState->var_pf_q7;//pState->q_values_after_init_code[6];//0.0f;
  1549. *pState->m_shape[i].var_pf_q8 = *pState->var_pf_q8;//pState->q_values_after_init_code[7];//0.0f;
  1550. *pState->m_shape[i].var_pf_t1 = pState->m_shape[i].t_values_after_init_code[0];//0.0f;
  1551. *pState->m_shape[i].var_pf_t2 = pState->m_shape[i].t_values_after_init_code[1];//0.0f;
  1552. *pState->m_shape[i].var_pf_t3 = pState->m_shape[i].t_values_after_init_code[2];//0.0f;
  1553. *pState->m_shape[i].var_pf_t4 = pState->m_shape[i].t_values_after_init_code[3];//0.0f;
  1554. *pState->m_shape[i].var_pf_t5 = pState->m_shape[i].t_values_after_init_code[4];//0.0f;
  1555. *pState->m_shape[i].var_pf_t6 = pState->m_shape[i].t_values_after_init_code[5];//0.0f;
  1556. *pState->m_shape[i].var_pf_t7 = pState->m_shape[i].t_values_after_init_code[6];//0.0f;
  1557. *pState->m_shape[i].var_pf_t8 = pState->m_shape[i].t_values_after_init_code[7];//0.0f;
  1558. *pState->m_shape[i].var_pf_x = pState->m_shape[i].x;
  1559. *pState->m_shape[i].var_pf_y = pState->m_shape[i].y;
  1560. *pState->m_shape[i].var_pf_rad = pState->m_shape[i].rad;
  1561. *pState->m_shape[i].var_pf_ang = pState->m_shape[i].ang;
  1562. *pState->m_shape[i].var_pf_tex_zoom = pState->m_shape[i].tex_zoom;
  1563. *pState->m_shape[i].var_pf_tex_ang = pState->m_shape[i].tex_ang;
  1564. *pState->m_shape[i].var_pf_sides = pState->m_shape[i].sides;
  1565. *pState->m_shape[i].var_pf_additive = pState->m_shape[i].additive;
  1566. *pState->m_shape[i].var_pf_textured = pState->m_shape[i].textured;
  1567. *pState->m_shape[i].var_pf_thick = pState->m_shape[i].thickOutline;
  1568. *pState->m_shape[i].var_pf_r = pState->m_shape[i].r;
  1569. *pState->m_shape[i].var_pf_g = pState->m_shape[i].g;
  1570. *pState->m_shape[i].var_pf_b = pState->m_shape[i].b;
  1571. *pState->m_shape[i].var_pf_a = pState->m_shape[i].a;
  1572. *pState->m_shape[i].var_pf_r2 = pState->m_shape[i].r2;
  1573. *pState->m_shape[i].var_pf_g2 = pState->m_shape[i].g2;
  1574. *pState->m_shape[i].var_pf_b2 = pState->m_shape[i].b2;
  1575. *pState->m_shape[i].var_pf_a2 = pState->m_shape[i].a2;
  1576. *pState->m_shape[i].var_pf_border_r = pState->m_shape[i].border_r;
  1577. *pState->m_shape[i].var_pf_border_g = pState->m_shape[i].border_g;
  1578. *pState->m_shape[i].var_pf_border_b = pState->m_shape[i].border_b;
  1579. *pState->m_shape[i].var_pf_border_a = pState->m_shape[i].border_a;
  1580. }
  1581. void CPlugin::LoadCustomWavePerFrameEvallibVars(CState* pState, int i)
  1582. {
  1583. *pState->m_wave[i].var_pf_time = (double)(GetTime() - m_fStartTime);
  1584. *pState->m_wave[i].var_pf_frame = (double)GetFrame();
  1585. *pState->m_wave[i].var_pf_fps = (double)GetFps();
  1586. *pState->m_wave[i].var_pf_progress = (GetTime() - m_fPresetStartTime) / (m_fNextPresetTime - m_fPresetStartTime);
  1587. *pState->m_wave[i].var_pf_bass = (double)mysound.imm_rel[0];
  1588. *pState->m_wave[i].var_pf_mid = (double)mysound.imm_rel[1];
  1589. *pState->m_wave[i].var_pf_treb = (double)mysound.imm_rel[2];
  1590. *pState->m_wave[i].var_pf_bass_att = (double)mysound.avg_rel[0];
  1591. *pState->m_wave[i].var_pf_mid_att = (double)mysound.avg_rel[1];
  1592. *pState->m_wave[i].var_pf_treb_att = (double)mysound.avg_rel[2];
  1593. *pState->m_wave[i].var_pf_q1 = *pState->var_pf_q1;//pState->q_values_after_init_code[0];//0.0f;
  1594. *pState->m_wave[i].var_pf_q2 = *pState->var_pf_q2;//pState->q_values_after_init_code[1];//0.0f;
  1595. *pState->m_wave[i].var_pf_q3 = *pState->var_pf_q3;//pState->q_values_after_init_code[2];//0.0f;
  1596. *pState->m_wave[i].var_pf_q4 = *pState->var_pf_q4;//pState->q_values_after_init_code[3];//0.0f;
  1597. *pState->m_wave[i].var_pf_q5 = *pState->var_pf_q5;//pState->q_values_after_init_code[4];//0.0f;
  1598. *pState->m_wave[i].var_pf_q6 = *pState->var_pf_q6;//pState->q_values_after_init_code[5];//0.0f;
  1599. *pState->m_wave[i].var_pf_q7 = *pState->var_pf_q7;//pState->q_values_after_init_code[6];//0.0f;
  1600. *pState->m_wave[i].var_pf_q8 = *pState->var_pf_q8;//pState->q_values_after_init_code[7];//0.0f;
  1601. *pState->m_wave[i].var_pf_t1 = pState->m_wave[i].t_values_after_init_code[0];//0.0f;
  1602. *pState->m_wave[i].var_pf_t2 = pState->m_wave[i].t_values_after_init_code[1];//0.0f;
  1603. *pState->m_wave[i].var_pf_t3 = pState->m_wave[i].t_values_after_init_code[2];//0.0f;
  1604. *pState->m_wave[i].var_pf_t4 = pState->m_wave[i].t_values_after_init_code[3];//0.0f;
  1605. *pState->m_wave[i].var_pf_t5 = pState->m_wave[i].t_values_after_init_code[4];//0.0f;
  1606. *pState->m_wave[i].var_pf_t6 = pState->m_wave[i].t_values_after_init_code[5];//0.0f;
  1607. *pState->m_wave[i].var_pf_t7 = pState->m_wave[i].t_values_after_init_code[6];//0.0f;
  1608. *pState->m_wave[i].var_pf_t8 = pState->m_wave[i].t_values_after_init_code[7];//0.0f;
  1609. *pState->m_wave[i].var_pf_r = pState->m_wave[i].r;
  1610. *pState->m_wave[i].var_pf_g = pState->m_wave[i].g;
  1611. *pState->m_wave[i].var_pf_b = pState->m_wave[i].b;
  1612. *pState->m_wave[i].var_pf_a = pState->m_wave[i].a;
  1613. }
  1614. void CPlugin::DrawCustomWaves()
  1615. {
  1616. LPDIRECT3DDEVICE9 lpDevice = GetDevice();
  1617. if (!lpDevice)
  1618. return;
  1619. lpDevice->SetTexture(0, NULL);
  1620. lpDevice->SetFVF( WFVERTEX_FORMAT );
  1621. // note: read in all sound data from CPluginShell's m_sound
  1622. int num_reps = (m_pState->m_bBlending) ? 2 : 1;
  1623. for (int rep=0; rep<num_reps; rep++)
  1624. {
  1625. CState *pState = (rep==0) ? m_pState : m_pOldState;
  1626. float alpha_mult = 1;
  1627. if (num_reps==2)
  1628. alpha_mult = (rep==0) ? m_pState->m_fBlendProgress : (1-m_pState->m_fBlendProgress);
  1629. for (int i=0; i<MAX_CUSTOM_WAVES; i++)
  1630. {
  1631. if (pState->m_wave[i].enabled)
  1632. {
  1633. int nSamples = pState->m_wave[i].samples;
  1634. int max_samples = pState->m_wave[i].bSpectrum ? 512 : NUM_WAVEFORM_SAMPLES;
  1635. if (nSamples > max_samples)
  1636. nSamples = max_samples;
  1637. nSamples -= pState->m_wave[i].sep;
  1638. if ((nSamples >= 2) || (pState->m_wave[i].bUseDots && nSamples >= 1))
  1639. {
  1640. int j;
  1641. float tempdata[2][512];
  1642. float mult = ((pState->m_wave[i].bSpectrum) ? 0.15f : 0.004f) * pState->m_wave[i].scaling * pState->m_fWaveScale.eval(-1);
  1643. float *pdata1 = (pState->m_wave[i].bSpectrum) ? m_sound.fSpectrum[0] : m_sound.fWaveform[0];
  1644. float *pdata2 = (pState->m_wave[i].bSpectrum) ? m_sound.fSpectrum[1] : m_sound.fWaveform[1];
  1645. // initialize tempdata[2][512]
  1646. int j0 = (pState->m_wave[i].bSpectrum) ? 0 : (max_samples - nSamples)/2/**(1-pState->m_wave[i].bSpectrum)*/ - pState->m_wave[i].sep/2;
  1647. int j1 = (pState->m_wave[i].bSpectrum) ? 0 : (max_samples - nSamples)/2/**(1-pState->m_wave[i].bSpectrum)*/ + pState->m_wave[i].sep/2;
  1648. float t = (pState->m_wave[i].bSpectrum) ? (max_samples - pState->m_wave[i].sep)/(float)nSamples : 1;
  1649. float mix1 = powf(pState->m_wave[i].smoothing*0.98f, 0.5f); // lower exponent -> more default smoothing
  1650. float mix2 = 1-mix1;
  1651. // SMOOTHING:
  1652. tempdata[0][0] = pdata1[j0];
  1653. tempdata[1][0] = pdata2[j1];
  1654. for (j=1; j<nSamples; j++)
  1655. {
  1656. tempdata[0][j] = pdata1[(int)(j*t)+j0]*mix2 + tempdata[0][j-1]*mix1;
  1657. tempdata[1][j] = pdata2[(int)(j*t)+j1]*mix2 + tempdata[1][j-1]*mix1;
  1658. }
  1659. // smooth again, backwards: [this fixes the asymmetry of the beginning & end..]
  1660. for (j=nSamples-2; j>=0; j--)
  1661. {
  1662. tempdata[0][j] = tempdata[0][j]*mix2 + tempdata[0][j+1]*mix1;
  1663. tempdata[1][j] = tempdata[1][j]*mix2 + tempdata[1][j+1]*mix1;
  1664. }
  1665. // finally, scale to final size:
  1666. for (j=0; j<nSamples; j++)
  1667. {
  1668. tempdata[0][j] *= mult;
  1669. tempdata[1][j] *= mult;
  1670. }
  1671. // 1. execute per-frame code
  1672. LoadCustomWavePerFrameEvallibVars(pState, i);
  1673. // 2.a. do just a once-per-frame init for the *per-point* *READ-ONLY* variables
  1674. // (the non-read-only ones will be reset/restored at the start of each vertex)
  1675. *pState->m_wave[i].var_pp_time = *pState->m_wave[i].var_pf_time;
  1676. *pState->m_wave[i].var_pp_fps = *pState->m_wave[i].var_pf_fps;
  1677. *pState->m_wave[i].var_pp_frame = *pState->m_wave[i].var_pf_frame;
  1678. *pState->m_wave[i].var_pp_progress = *pState->m_wave[i].var_pf_progress;
  1679. *pState->m_wave[i].var_pp_bass = *pState->m_wave[i].var_pf_bass;
  1680. *pState->m_wave[i].var_pp_mid = *pState->m_wave[i].var_pf_mid;
  1681. *pState->m_wave[i].var_pp_treb = *pState->m_wave[i].var_pf_treb;
  1682. *pState->m_wave[i].var_pp_bass_att = *pState->m_wave[i].var_pf_bass_att;
  1683. *pState->m_wave[i].var_pp_mid_att = *pState->m_wave[i].var_pf_mid_att;
  1684. *pState->m_wave[i].var_pp_treb_att = *pState->m_wave[i].var_pf_treb_att;
  1685. executeCode(pState->m_wave[i].m_pf_codehandle);
  1686. *pState->m_wave[i].var_pp_q1 = *pState->m_wave[i].var_pf_q1;
  1687. *pState->m_wave[i].var_pp_q2 = *pState->m_wave[i].var_pf_q2;
  1688. *pState->m_wave[i].var_pp_q3 = *pState->m_wave[i].var_pf_q3;
  1689. *pState->m_wave[i].var_pp_q4 = *pState->m_wave[i].var_pf_q4;
  1690. *pState->m_wave[i].var_pp_q5 = *pState->m_wave[i].var_pf_q5;
  1691. *pState->m_wave[i].var_pp_q6 = *pState->m_wave[i].var_pf_q6;
  1692. *pState->m_wave[i].var_pp_q7 = *pState->m_wave[i].var_pf_q7;
  1693. *pState->m_wave[i].var_pp_q8 = *pState->m_wave[i].var_pf_q8;
  1694. *pState->m_wave[i].var_pp_t1 = *pState->m_wave[i].var_pf_t1;
  1695. *pState->m_wave[i].var_pp_t2 = *pState->m_wave[i].var_pf_t2;
  1696. *pState->m_wave[i].var_pp_t3 = *pState->m_wave[i].var_pf_t3;
  1697. *pState->m_wave[i].var_pp_t4 = *pState->m_wave[i].var_pf_t4;
  1698. *pState->m_wave[i].var_pp_t5 = *pState->m_wave[i].var_pf_t5;
  1699. *pState->m_wave[i].var_pp_t6 = *pState->m_wave[i].var_pf_t6;
  1700. *pState->m_wave[i].var_pp_t7 = *pState->m_wave[i].var_pf_t7;
  1701. *pState->m_wave[i].var_pp_t8 = *pState->m_wave[i].var_pf_t8;
  1702. // 2. for each point, execute per-point code
  1703. #ifndef _NO_EXPR_
  1704. resetVars(pState->m_wave[i].m_pp_vars);
  1705. #endif
  1706. // to do:
  1707. // -add any of the m_wave[i].xxx menu-accessible vars to the code?
  1708. WFVERTEX v[512];
  1709. float j_mult = 1.0f/(float)(nSamples-1);
  1710. for (j=0; j<nSamples; j++)
  1711. {
  1712. float t = j*j_mult;
  1713. float value1 = tempdata[0][j];
  1714. float value2 = tempdata[1][j];
  1715. *pState->m_wave[i].var_pp_sample = t;
  1716. *pState->m_wave[i].var_pp_value1 = value1;
  1717. *pState->m_wave[i].var_pp_value2 = value2;
  1718. *pState->m_wave[i].var_pp_x = 0.5f + value1;
  1719. *pState->m_wave[i].var_pp_y = 0.5f + value2;
  1720. *pState->m_wave[i].var_pp_r = *pState->m_wave[i].var_pf_r;
  1721. *pState->m_wave[i].var_pp_g = *pState->m_wave[i].var_pf_g;
  1722. *pState->m_wave[i].var_pp_b = *pState->m_wave[i].var_pf_b;
  1723. *pState->m_wave[i].var_pp_a = *pState->m_wave[i].var_pf_a;
  1724. #ifndef _NO_EXPR_
  1725. executeCode(pState->m_wave[i].m_pp_codehandle);
  1726. #endif
  1727. v[j].x = (float)(*pState->m_wave[i].var_pp_x* 2-1);//*ASPECT;
  1728. v[j].y = (float)(*pState->m_wave[i].var_pp_y*-2+1);
  1729. v[j].z = 0;
  1730. v[j].Diffuse =
  1731. ((((int)(*pState->m_wave[i].var_pp_a * 255 * alpha_mult)) & 0xFF) << 24) |
  1732. ((((int)(*pState->m_wave[i].var_pp_r * 255)) & 0xFF) << 16) |
  1733. ((((int)(*pState->m_wave[i].var_pp_g * 255)) & 0xFF) << 8) |
  1734. ((((int)(*pState->m_wave[i].var_pp_b * 255)) & 0xFF) );
  1735. }
  1736. #ifndef _NO_EXPR_
  1737. resetVars(NULL);
  1738. #endif
  1739. // save changes to t1-t8 this frame
  1740. /*
  1741. pState->m_wave[i].t_values_after_init_code[0] = *pState->m_wave[i].var_pp_t1;
  1742. pState->m_wave[i].t_values_after_init_code[1] = *pState->m_wave[i].var_pp_t2;
  1743. pState->m_wave[i].t_values_after_init_code[2] = *pState->m_wave[i].var_pp_t3;
  1744. pState->m_wave[i].t_values_after_init_code[3] = *pState->m_wave[i].var_pp_t4;
  1745. pState->m_wave[i].t_values_after_init_code[4] = *pState->m_wave[i].var_pp_t5;
  1746. pState->m_wave[i].t_values_after_init_code[5] = *pState->m_wave[i].var_pp_t6;
  1747. pState->m_wave[i].t_values_after_init_code[6] = *pState->m_wave[i].var_pp_t7;
  1748. pState->m_wave[i].t_values_after_init_code[7] = *pState->m_wave[i].var_pp_t8;
  1749. */
  1750. // 3. draw it
  1751. lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
  1752. lpDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
  1753. lpDevice->SetRenderState(D3DRS_DESTBLEND, pState->m_wave[i].bAdditive ? D3DBLEND_ONE : D3DBLEND_INVSRCALPHA);
  1754. float ptsize = ((m_nTexSize >= 1024) ? 2.0f : 1.0f) + (pState->m_wave[i].bDrawThick ? 1.0f : 0.0f);
  1755. if (pState->m_wave[i].bUseDots)
  1756. lpDevice->SetRenderState(D3DRS_POINTSIZE, *((DWORD*)&ptsize) );
  1757. int its = (pState->m_wave[i].bDrawThick && !pState->m_wave[i].bUseDots) ? 4 : 1;
  1758. float x_inc = 2.0f / (float)m_nTexSize;
  1759. for (int it=0; it<its; it++)
  1760. {
  1761. switch(it)
  1762. {
  1763. case 0: break;
  1764. case 1: for (j=0; j<nSamples; j++) v[j].x += x_inc; break; // draw fat dots
  1765. case 2: for (j=0; j<nSamples; j++) v[j].y += x_inc; break; // draw fat dots
  1766. case 3: for (j=0; j<nSamples; j++) v[j].x -= x_inc; break; // draw fat dots
  1767. }
  1768. lpDevice->DrawPrimitiveUP(pState->m_wave[i].bUseDots ? D3DPT_POINTLIST : D3DPT_LINESTRIP, nSamples - (pState->m_wave[i].bUseDots ? 0 : 1), (void*)v, sizeof(WFVERTEX));
  1769. }
  1770. ptsize = 1.0f;
  1771. if (pState->m_wave[i].bUseDots)
  1772. lpDevice->SetRenderState(D3DRS_POINTSIZE, *((DWORD*)&ptsize) );
  1773. }
  1774. }
  1775. }
  1776. }
  1777. lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
  1778. lpDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
  1779. lpDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
  1780. }
  1781. void CPlugin::DrawWave(float *fL, float *fR)
  1782. {
  1783. //return;
  1784. LPDIRECT3DDEVICE9 lpDevice = GetDevice();
  1785. if (!lpDevice)
  1786. return;
  1787. lpDevice->SetTexture(0, NULL);
  1788. lpDevice->SetFVF( WFVERTEX_FORMAT );
  1789. int i;
  1790. WFVERTEX v1[576+1], v2[576+1];
  1791. /*
  1792. m_lpD3DDev->lpDevice->SetRenderState(D3DRENDERSTATE_SHADEMODE, D3DSHADE_GOURAUD); //D3DSHADE_FLAT
  1793. m_lpD3DDev->lpDevice->SetRenderState(D3DRENDERSTATE_SPECULARENABLE, FALSE);
  1794. m_lpD3DDev->lpDevice->SetRenderState(D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
  1795. if (m_D3DDevDesc.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_DITHER)
  1796. m_lpD3DDev->lpDevice->SetRenderState(D3DRENDERSTATE_DITHERENABLE, TRUE);
  1797. m_lpD3DDev->lpDevice->SetRenderState(D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
  1798. m_lpD3DDev->lpDevice->SetRenderState(D3DRENDERSTATE_LIGHTING, FALSE);
  1799. m_lpD3DDev->lpDevice->SetRenderState(D3DRENDERSTATE_COLORVERTEX, TRUE);
  1800. m_lpD3DDev->lpDevice->SetRenderState(D3DRENDERSTATE_FILLMODE, D3DFILL_WIREFRAME); // vs. SOLID
  1801. m_lpD3DDev->lpDevice->SetRenderState(D3DRENDERSTATE_AMBIENT, D3DCOLOR_RGBA_01(1,1,1,1));
  1802. hr = m_lpD3DDev->SetTexture(0, NULL);
  1803. if (hr != D3D_OK)
  1804. {
  1805. //dumpmsg("Draw(): ERROR: SetTexture");
  1806. //IdentifyD3DError(hr);
  1807. }
  1808. */
  1809. lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
  1810. lpDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
  1811. lpDevice->SetRenderState(D3DRS_DESTBLEND, (*m_pState->var_pf_wave_additive) ? D3DBLEND_ONE : D3DBLEND_INVSRCALPHA);
  1812. //float cr = m_pState->m_waveR.eval(GetTime());
  1813. //float cg = m_pState->m_waveG.eval(GetTime());
  1814. //float cb = m_pState->m_waveB.eval(GetTime());
  1815. float cr = (float)(*m_pState->var_pf_wave_r);
  1816. float cg = (float)(*m_pState->var_pf_wave_g);
  1817. float cb = (float)(*m_pState->var_pf_wave_b);
  1818. float cx = (float)(*m_pState->var_pf_wave_x);
  1819. float cy = (float)(*m_pState->var_pf_wave_y); // note: it was backwards (top==1) in the original milkdrop, so we keep it that way!
  1820. float fWaveParam = (float)(*m_pState->var_pf_wave_mystery);
  1821. /*if (m_pState->m_bBlending)
  1822. {
  1823. cr = cr*(m_pState->m_fBlendProgress) + (1.0f-m_pState->m_fBlendProgress)*((float)(*m_pOldState->var_pf_wave_r));
  1824. cg = cg*(m_pState->m_fBlendProgress) + (1.0f-m_pState->m_fBlendProgress)*((float)(*m_pOldState->var_pf_wave_g));
  1825. cb = cb*(m_pState->m_fBlendProgress) + (1.0f-m_pState->m_fBlendProgress)*((float)(*m_pOldState->var_pf_wave_b));
  1826. cx = cx*(m_pState->m_fBlendProgress) + (1.0f-m_pState->m_fBlendProgress)*((float)(*m_pOldState->var_pf_wave_x));
  1827. cy = cy*(m_pState->m_fBlendProgress) + (1.0f-m_pState->m_fBlendProgress)*((float)(*m_pOldState->var_pf_wave_y));
  1828. fWaveParam = fWaveParam*(m_pState->m_fBlendProgress) + (1.0f-m_pState->m_fBlendProgress)*((float)(*m_pOldState->var_pf_wave_mystery));
  1829. }*/
  1830. if (cr < 0) cr = 0;
  1831. if (cg < 0) cg = 0;
  1832. if (cb < 0) cb = 0;
  1833. if (cr > 1) cr = 1;
  1834. if (cg > 1) cg = 1;
  1835. if (cb > 1) cb = 1;
  1836. // maximize color:
  1837. if (*m_pState->var_pf_wave_brighten)
  1838. {
  1839. float fMaximizeWaveColorAmount = 1.0f;
  1840. float max = cr;
  1841. if (max < cg) max = cg;
  1842. if (max < cb) max = cb;
  1843. if (max > 0.01f)
  1844. {
  1845. cr = cr/max*fMaximizeWaveColorAmount + cr*(1.0f - fMaximizeWaveColorAmount);
  1846. cg = cg/max*fMaximizeWaveColorAmount + cg*(1.0f - fMaximizeWaveColorAmount);
  1847. cb = cb/max*fMaximizeWaveColorAmount + cb*(1.0f - fMaximizeWaveColorAmount);
  1848. }
  1849. }
  1850. float fWavePosX = cx*2.0f - 1.0f; // go from 0..1 user-range to -1..1 D3D range
  1851. float fWavePosY = cy*2.0f - 1.0f;
  1852. float bass_rel = mysound.imm[0];
  1853. float mid_rel = mysound.imm[1];
  1854. float treble_rel = mysound.imm[2];
  1855. int sample_offset = 0;
  1856. int new_wavemode = (int)(*m_pState->var_pf_wave_mode) % NUM_WAVES; // since it can be changed from per-frame code!
  1857. int its = (m_pState->m_bBlending && (new_wavemode != m_pState->m_nOldWaveMode)) ? 2 : 1;
  1858. int nVerts1 = 0;
  1859. int nVerts2 = 0;
  1860. int nBreak1 = -1;
  1861. int nBreak2 = -1;
  1862. float alpha1, alpha2;
  1863. for (int it=0; it<its; it++)
  1864. {
  1865. int wave = (it==0) ? new_wavemode : m_pState->m_nOldWaveMode;
  1866. int nVerts = NUM_WAVEFORM_SAMPLES; // allowed to peek ahead 64 (i.e. left is [i], right is [i+64])
  1867. int nBreak = -1;
  1868. WFVERTEX *v = (it==0) ? v1 : v2;
  1869. ZeroMemory(v, sizeof(WFVERTEX)*nVerts);
  1870. float alpha = (float)(*m_pState->var_pf_wave_a);//m_pState->m_fWaveAlpha.eval(GetTime());
  1871. switch(wave)
  1872. {
  1873. case 0:
  1874. // circular wave
  1875. nVerts /= 2;
  1876. sample_offset = (NUM_WAVEFORM_SAMPLES-nVerts)/2;//mysound.GoGoAlignatron(nVerts * 12/10); // only call this once nVerts is final!
  1877. if (m_pState->m_bModWaveAlphaByVolume)
  1878. alpha *= ((mysound.imm_rel[0] + mysound.imm_rel[1] + mysound.imm_rel[2])*0.333f - m_pState->m_fModWaveAlphaStart.eval(GetTime()))/(m_pState->m_fModWaveAlphaEnd.eval(GetTime()) - m_pState->m_fModWaveAlphaStart.eval(GetTime()));
  1879. if (alpha < 0) alpha = 0;
  1880. if (alpha > 1) alpha = 1;
  1881. //color = D3DCOLOR_RGBA_01(cr, cg, cb, alpha);
  1882. {
  1883. float inv_nverts_minus_one = 1.0f/(float)(nVerts-1);
  1884. for (i=0; i<nVerts; i++)
  1885. {
  1886. float rad = 0.5f + 0.4f*fR[i+sample_offset] + fWaveParam;
  1887. float ang = (i)*inv_nverts_minus_one*6.28f + GetTime()*0.2f;
  1888. if (i < nVerts/10)
  1889. {
  1890. float mix = i/(nVerts*0.1f);
  1891. mix = 0.5f - 0.5f*cosf(mix * 3.1416f);
  1892. float rad_2 = 0.5f + 0.4f*fR[i + nVerts + sample_offset] + fWaveParam;
  1893. rad = rad_2*(1.0f-mix) + rad*(mix);
  1894. }
  1895. v[i].x = rad*cosf(ang) * ASPECT + fWavePosX; // 0.75 = adj. for aspect ratio
  1896. v[i].y = rad*sinf(ang) + fWavePosY;
  1897. //v[i].Diffuse = color;
  1898. }
  1899. }
  1900. // dupe last vertex to connect the lines; skip if blending
  1901. if (!m_pState->m_bBlending)
  1902. {
  1903. nVerts++;
  1904. memcpy(&v[nVerts-1], &v[0], sizeof(WFVERTEX));
  1905. }
  1906. break;
  1907. case 1:
  1908. // x-y osc. that goes around in a spiral, in time
  1909. alpha *= 1.25f;
  1910. if (m_pState->m_bModWaveAlphaByVolume)
  1911. alpha *= ((mysound.imm_rel[0] + mysound.imm_rel[1] + mysound.imm_rel[2])*0.333f - m_pState->m_fModWaveAlphaStart.eval(GetTime()))/(m_pState->m_fModWaveAlphaEnd.eval(GetTime()) - m_pState->m_fModWaveAlphaStart.eval(GetTime()));
  1912. if (alpha < 0) alpha = 0;
  1913. if (alpha > 1) alpha = 1;
  1914. //color = D3DCOLOR_RGBA_01(cr, cg, cb, alpha);
  1915. nVerts /= 2;
  1916. for (i=0; i<nVerts; i++)
  1917. {
  1918. float rad = 0.53f + 0.43f*fR[i] + fWaveParam;
  1919. float ang = fL[i+32] * 1.57f + GetTime()*2.3f;
  1920. v[i].x = rad*cosf(ang) * ASPECT + fWavePosX; // 0.75 = adj. for aspect ratio
  1921. v[i].y = rad*sinf(ang) + fWavePosY;
  1922. //v[i].Diffuse = color;//(D3DCOLOR_RGBA_01(cr, cg, cb, alpha*min(1, max(0, fL[i])));
  1923. }
  1924. break;
  1925. case 2:
  1926. // centered spiro (alpha constant)
  1927. // aimed at not being so sound-responsive, but being very "nebula-like"
  1928. // difference is that alpha is constant (and faint), and waves a scaled way up
  1929. switch(m_nTexSize)
  1930. {
  1931. case 256: alpha *= 0.07f; break;
  1932. case 512: alpha *= 0.09f; break;
  1933. case 1024: alpha *= 0.11f; break;
  1934. case 2048: alpha *= 0.13f; break;
  1935. }
  1936. if (m_pState->m_bModWaveAlphaByVolume)
  1937. alpha *= ((mysound.imm_rel[0] + mysound.imm_rel[1] + mysound.imm_rel[2])*0.333f - m_pState->m_fModWaveAlphaStart.eval(GetTime()))/(m_pState->m_fModWaveAlphaEnd.eval(GetTime()) - m_pState->m_fModWaveAlphaStart.eval(GetTime()));
  1938. if (alpha < 0) alpha = 0;
  1939. if (alpha > 1) alpha = 1;
  1940. //color = D3DCOLOR_RGBA_01(cr, cg, cb, alpha);
  1941. for (i=0; i<nVerts; i++)
  1942. {
  1943. v[i].x = fR[i] * ASPECT + fWavePosX;//((pR[i] ^ 128) - 128)/90.0f * ASPECT; // 0.75 = adj. for aspect ratio
  1944. v[i].y = fL[i+32] + fWavePosY;//((pL[i+32] ^ 128) - 128)/90.0f;
  1945. //v[i].Diffuse = color;
  1946. }
  1947. break;
  1948. case 3:
  1949. // centered spiro (alpha tied to volume)
  1950. // aimed at having a strong audio-visual tie-in
  1951. // colors are always bright (no darks)
  1952. switch(m_nTexSize)
  1953. {
  1954. case 256: alpha = 0.075f; break;
  1955. case 512: alpha = 0.150f; break;
  1956. case 1024: alpha = 0.220f; break;
  1957. case 2048: alpha = 0.330f; break;
  1958. }
  1959. alpha *= 1.3f;
  1960. alpha *= powf(treble_rel, 2.0f);
  1961. if (m_pState->m_bModWaveAlphaByVolume)
  1962. alpha *= ((mysound.imm_rel[0] + mysound.imm_rel[1] + mysound.imm_rel[2])*0.333f - m_pState->m_fModWaveAlphaStart.eval(GetTime()))/(m_pState->m_fModWaveAlphaEnd.eval(GetTime()) - m_pState->m_fModWaveAlphaStart.eval(GetTime()));
  1963. if (alpha < 0) alpha = 0;
  1964. if (alpha > 1) alpha = 1;
  1965. //color = D3DCOLOR_RGBA_01(cr, cg, cb, alpha);
  1966. for (i=0; i<nVerts; i++)
  1967. {
  1968. v[i].x = fR[i] * ASPECT + fWavePosX;//((pR[i] ^ 128) - 128)/90.0f * ASPECT; // 0.75 = adj. for aspect ratio
  1969. v[i].y = fL[i+32] + fWavePosY;//((pL[i+32] ^ 128) - 128)/90.0f;
  1970. //v[i].Diffuse = color;
  1971. }
  1972. break;
  1973. case 4:
  1974. // horizontal "script", left channel
  1975. if (nVerts > m_nTexSize/3)
  1976. nVerts = m_nTexSize/3;
  1977. sample_offset = (NUM_WAVEFORM_SAMPLES-nVerts)/2;//mysound.GoGoAlignatron(nVerts + 25); // only call this once nVerts is final!
  1978. /*
  1979. if (treble_rel > treb_thresh_for_wave6)
  1980. {
  1981. //alpha = 1.0f;
  1982. treb_thresh_for_wave6 = treble_rel * 1.025f;
  1983. }
  1984. else
  1985. {
  1986. alpha *= 0.2f;
  1987. treb_thresh_for_wave6 *= 0.996f; // fixme: make this fps-independent
  1988. }
  1989. */
  1990. if (m_pState->m_bModWaveAlphaByVolume)
  1991. alpha *= ((mysound.imm_rel[0] + mysound.imm_rel[1] + mysound.imm_rel[2])*0.333f - m_pState->m_fModWaveAlphaStart.eval(GetTime()))/(m_pState->m_fModWaveAlphaEnd.eval(GetTime()) - m_pState->m_fModWaveAlphaStart.eval(GetTime()));
  1992. if (alpha < 0) alpha = 0;
  1993. if (alpha > 1) alpha = 1;
  1994. //color = D3DCOLOR_RGBA_01(cr, cg, cb, alpha);
  1995. {
  1996. float w1 = 0.45f + 0.5f*(fWaveParam*0.5f + 0.5f); // 0.1 - 0.9
  1997. float w2 = 1.0f - w1;
  1998. float inv_nverts = 1.0f/(float)(nVerts);
  1999. for (i=0; i<nVerts; i++)
  2000. {
  2001. v[i].x = -1.0f + 2.0f*(i*inv_nverts) + fWavePosX;
  2002. v[i].y = fL[i+sample_offset]*0.47f + fWavePosY;//((pL[i] ^ 128) - 128)/270.0f;
  2003. v[i].x += fR[i+25+sample_offset]*0.44f;//((pR[i+25] ^ 128) - 128)/290.0f;
  2004. //v[i].Diffuse = color;
  2005. // momentum
  2006. if (i>1)
  2007. {
  2008. v[i].x = v[i].x*w2 + w1*(v[i-1].x*2.0f - v[i-2].x);
  2009. v[i].y = v[i].y*w2 + w1*(v[i-1].y*2.0f - v[i-2].y);
  2010. }
  2011. }
  2012. /*
  2013. // center on Y
  2014. float avg_y = 0;
  2015. for (i=0; i<nVerts; i++)
  2016. avg_y += v[i].y;
  2017. avg_y /= (float)nVerts;
  2018. avg_y *= 0.5f; // damp the movement
  2019. for (i=0; i<nVerts; i++)
  2020. v[i].y -= avg_y;
  2021. */
  2022. }
  2023. break;
  2024. case 5:
  2025. // weird explosive complex # thingy
  2026. switch(m_nTexSize)
  2027. {
  2028. case 256: alpha *= 0.07f; break;
  2029. case 512: alpha *= 0.09f; break;
  2030. case 1024: alpha *= 0.11f; break;
  2031. case 2048: alpha *= 0.13f; break;
  2032. }
  2033. if (m_pState->m_bModWaveAlphaByVolume)
  2034. alpha *= ((mysound.imm_rel[0] + mysound.imm_rel[1] + mysound.imm_rel[2])*0.333f - m_pState->m_fModWaveAlphaStart.eval(GetTime()))/(m_pState->m_fModWaveAlphaEnd.eval(GetTime()) - m_pState->m_fModWaveAlphaStart.eval(GetTime()));
  2035. if (alpha < 0) alpha = 0;
  2036. if (alpha > 1) alpha = 1;
  2037. //color = D3DCOLOR_RGBA_01(cr, cg, cb, alpha);
  2038. {
  2039. float cos_rot = cosf(GetTime()*0.3f);
  2040. float sin_rot = sinf(GetTime()*0.3f);
  2041. for (i=0; i<nVerts; i++)
  2042. {
  2043. float x0 = (fR[i]*fL[i+32] + fL[i]*fR[i+32]);
  2044. float y0 = (fR[i]*fR[i] - fL[i+32]*fL[i+32]);
  2045. v[i].x = (x0*cos_rot - y0*sin_rot)*ASPECT + fWavePosX;
  2046. v[i].y = (x0*sin_rot + y0*cos_rot) + fWavePosY;
  2047. //v[i].Diffuse = color;
  2048. }
  2049. }
  2050. break;
  2051. case 6:
  2052. case 7:
  2053. case 8:
  2054. // 6: angle-adjustable left channel, with temporal wave alignment;
  2055. // fWaveParam controls the angle at which it's drawn
  2056. // fWavePosX slides the wave away from the center, transversely.
  2057. // fWavePosY does nothing
  2058. //
  2059. // 7: same, except there are two channels shown, and
  2060. // fWavePosY determines the separation distance.
  2061. //
  2062. // 8: same as 6, except using the spectrum analyzer (UNFINISHED)
  2063. //
  2064. nVerts /= 2;
  2065. if (nVerts > m_nTexSize/3)
  2066. nVerts = m_nTexSize/3;
  2067. if (wave==8)
  2068. nVerts = 256;
  2069. else
  2070. sample_offset = (NUM_WAVEFORM_SAMPLES-nVerts)/2;//mysound.GoGoAlignatron(nVerts); // only call this once nVerts is final!
  2071. if (m_pState->m_bModWaveAlphaByVolume)
  2072. alpha *= ((mysound.imm_rel[0] + mysound.imm_rel[1] + mysound.imm_rel[2])*0.333f - m_pState->m_fModWaveAlphaStart.eval(GetTime()))/(m_pState->m_fModWaveAlphaEnd.eval(GetTime()) - m_pState->m_fModWaveAlphaStart.eval(GetTime()));
  2073. if (alpha < 0) alpha = 0;
  2074. if (alpha > 1) alpha = 1;
  2075. //color = D3DCOLOR_RGBA_01(cr, cg, cb, alpha);
  2076. {
  2077. float ang = 1.57f*fWaveParam; // from -PI/2 to PI/2
  2078. float dx = cosf(ang);
  2079. float dy = sinf(ang);
  2080. float edge_x[2], edge_y[2];
  2081. //edge_x[0] = fWavePosX - dx*3.0f;
  2082. //edge_y[0] = fWavePosY - dy*3.0f;
  2083. //edge_x[1] = fWavePosX + dx*3.0f;
  2084. //edge_y[1] = fWavePosY + dy*3.0f;
  2085. edge_x[0] = fWavePosX*cosf(ang + 1.57f) - dx*3.0f;
  2086. edge_y[0] = fWavePosX*sinf(ang + 1.57f) - dy*3.0f;
  2087. edge_x[1] = fWavePosX*cosf(ang + 1.57f) + dx*3.0f;
  2088. edge_y[1] = fWavePosX*sinf(ang + 1.57f) + dy*3.0f;
  2089. for (i=0; i<2; i++) // for each point defining the line
  2090. {
  2091. // clip the point against 4 edges of screen
  2092. // be a bit lenient (use +/-1.1 instead of +/-1.0)
  2093. // so the dual-wave doesn't end too soon, after the channels are moved apart
  2094. for (int j=0; j<4; j++)
  2095. {
  2096. float t;
  2097. bool bClip = false;
  2098. switch(j)
  2099. {
  2100. case 0:
  2101. if (edge_x[i] > 1.1f)
  2102. {
  2103. t = (1.1f - edge_x[1-i]) / (edge_x[i] - edge_x[1-i]);
  2104. bClip = true;
  2105. }
  2106. break;
  2107. case 1:
  2108. if (edge_x[i] < -1.1f)
  2109. {
  2110. t = (-1.1f - edge_x[1-i]) / (edge_x[i] - edge_x[1-i]);
  2111. bClip = true;
  2112. }
  2113. break;
  2114. case 2:
  2115. if (edge_y[i] > 1.1f)
  2116. {
  2117. t = (1.1f - edge_y[1-i]) / (edge_y[i] - edge_y[1-i]);
  2118. bClip = true;
  2119. }
  2120. break;
  2121. case 3:
  2122. if (edge_y[i] < -1.1f)
  2123. {
  2124. t = (-1.1f - edge_y[1-i]) / (edge_y[i] - edge_y[1-i]);
  2125. bClip = true;
  2126. }
  2127. break;
  2128. }
  2129. if (bClip)
  2130. {
  2131. float dx = edge_x[i] - edge_x[1-i];
  2132. float dy = edge_y[i] - edge_y[1-i];
  2133. edge_x[i] = edge_x[1-i] + dx*t;
  2134. edge_y[i] = edge_y[1-i] + dy*t;
  2135. }
  2136. }
  2137. }
  2138. dx = (edge_x[1] - edge_x[0]) / (float)nVerts;
  2139. dy = (edge_y[1] - edge_y[0]) / (float)nVerts;
  2140. float ang2 = atan2f(dy,dx);
  2141. float perp_dx = cosf(ang2 + 1.57f);
  2142. float perp_dy = sinf(ang2 + 1.57f);
  2143. if (wave == 6)
  2144. for (i=0; i<nVerts; i++)
  2145. {
  2146. v[i].x = edge_x[0] + dx*i + perp_dx*0.25f*fL[i + sample_offset];
  2147. v[i].y = edge_y[0] + dy*i + perp_dy*0.25f*fL[i + sample_offset];
  2148. //v[i].Diffuse = color;
  2149. }
  2150. else if (wave == 8)
  2151. //256 verts
  2152. for (i=0; i<nVerts; i++)
  2153. {
  2154. float f = 0.1f*logf(mysound.fSpecLeft[i*2] + mysound.fSpecLeft[i*2+1]);
  2155. v[i].x = edge_x[0] + dx*i + perp_dx*f;
  2156. v[i].y = edge_y[0] + dy*i + perp_dy*f;
  2157. //v[i].Diffuse = color;
  2158. }
  2159. else
  2160. {
  2161. float sep = powf(fWavePosY*0.5f + 0.5f, 2.0f);
  2162. for (i=0; i<nVerts; i++)
  2163. {
  2164. v[i].x = edge_x[0] + dx*i + perp_dx*(0.25f*fL[i + sample_offset] + sep);
  2165. v[i].y = edge_y[0] + dy*i + perp_dy*(0.25f*fL[i + sample_offset] + sep);
  2166. //v[i].Diffuse = color;
  2167. }
  2168. //D3DPRIMITIVETYPE primtype = (*m_pState->var_pf_wave_usedots) ? D3DPT_POINTLIST : D3DPT_LINESTRIP;
  2169. //m_lpD3DDev->DrawPrimitive(primtype, D3DFVF_LVERTEX, (LPVOID)v, nVerts, NULL);
  2170. for (i=0; i<nVerts; i++)
  2171. {
  2172. v[i+nVerts].x = edge_x[0] + dx*i + perp_dx*(0.25f*fR[i + sample_offset] - sep);
  2173. v[i+nVerts].y = edge_y[0] + dy*i + perp_dy*(0.25f*fR[i + sample_offset] - sep);
  2174. //v[i+nVerts].Diffuse = color;
  2175. }
  2176. nBreak = nVerts;
  2177. nVerts *= 2;
  2178. }
  2179. }
  2180. break;
  2181. }
  2182. if (it==0)
  2183. {
  2184. nVerts1 = nVerts;
  2185. nBreak1 = nBreak;
  2186. alpha1 = alpha;
  2187. }
  2188. else
  2189. {
  2190. nVerts2 = nVerts;
  2191. nBreak2 = nBreak;
  2192. alpha2 = alpha;
  2193. }
  2194. }
  2195. // v1[] is for the current waveform
  2196. // v2[] is for the old waveform (from prev. preset - only used if blending)
  2197. // nVerts1 is the # of vertices in v1
  2198. // nVerts2 is the # of vertices in v2
  2199. // nBreak1 is the index of the point at which to break the solid line in v1[] (-1 if no break)
  2200. // nBreak2 is the index of the point at which to break the solid line in v2[] (-1 if no break)
  2201. float mix = CosineInterp(m_pState->m_fBlendProgress);
  2202. float mix2 = 1.0f - mix;
  2203. // blend 2 waveforms
  2204. if (nVerts2 > 0)
  2205. {
  2206. // note: this won't yet handle the case where (nBreak1 > 0 && nBreak2 > 0)
  2207. // in this case, code must break wave into THREE segments
  2208. float m = (nVerts2-1)/(float)nVerts1;
  2209. float x,y;
  2210. for (int i=0; i<nVerts1; i++)
  2211. {
  2212. float fIdx = i*m;
  2213. int nIdx = (int)fIdx;
  2214. float t = fIdx - nIdx;
  2215. if (nIdx == nBreak2-1)
  2216. {
  2217. x = v2[nIdx].x;
  2218. y = v2[nIdx].y;
  2219. nBreak1 = i+1;
  2220. }
  2221. else
  2222. {
  2223. x = v2[nIdx].x*(1-t) + v2[nIdx+1].x*(t);
  2224. y = v2[nIdx].y*(1-t) + v2[nIdx+1].y*(t);
  2225. }
  2226. v1[i].x = v1[i].x*(mix) + x*(mix2);
  2227. v1[i].y = v1[i].y*(mix) + y*(mix2);
  2228. }
  2229. }
  2230. // determine alpha
  2231. if (nVerts2 > 0)
  2232. {
  2233. alpha1 = alpha1*(mix) + alpha2*(1.0f-mix);
  2234. }
  2235. // apply color & alpha
  2236. // ALSO reverse all y values, to stay consistent with the pre-VMS milkdrop,
  2237. // which DIDN'T:
  2238. v1[0].Diffuse = D3DCOLOR_RGBA_01(cr, cg, cb, alpha1);
  2239. for (i=0; i<nVerts1; i++)
  2240. {
  2241. v1[i].Diffuse = v1[0].Diffuse;
  2242. v1[i].y = -v1[i].y;
  2243. }
  2244. // draw primitives
  2245. {
  2246. //D3DPRIMITIVETYPE primtype = (*m_pState->var_pf_wave_usedots) ? D3DPT_POINTLIST : D3DPT_LINESTRIP;
  2247. float x_inc = 2.0f / (float)m_nTexSize;
  2248. int drawing_its = ((*m_pState->var_pf_wave_thick || *m_pState->var_pf_wave_usedots) && (m_nTexSize >= 512)) ? 4 : 1;
  2249. for (int it=0; it<drawing_its; it++)
  2250. {
  2251. int j;
  2252. switch(it)
  2253. {
  2254. case 0: break;
  2255. case 1: for (j=0; j<nVerts1; j++) v1[j].x += x_inc; break; // draw fat dots
  2256. case 2: for (j=0; j<nVerts1; j++) v1[j].y += x_inc; break; // draw fat dots
  2257. case 3: for (j=0; j<nVerts1; j++) v1[j].x -= x_inc; break; // draw fat dots
  2258. }
  2259. if (nBreak1 == -1)
  2260. {
  2261. //m_lpD3DDev->DrawPrimitive(primtype, D3DFVF_LVERTEX, (LPVOID)v1, nVerts1, NULL);
  2262. if (*m_pState->var_pf_wave_usedots)
  2263. lpDevice->DrawPrimitiveUP(D3DPT_POINTLIST, nVerts1, (void*)v1, sizeof(WFVERTEX));
  2264. else
  2265. lpDevice->DrawPrimitiveUP(D3DPT_LINESTRIP, nVerts1-1, (void*)v1, sizeof(WFVERTEX));
  2266. }
  2267. else
  2268. {
  2269. //m_lpD3DDev->DrawPrimitive(primtype, D3DFVF_LVERTEX, (LPVOID)v1, nBreak1, NULL);
  2270. //m_lpD3DDev->DrawPrimitive(primtype, D3DFVF_LVERTEX, (LPVOID)&v1[nBreak1], nVerts1-nBreak1, NULL);
  2271. if (*m_pState->var_pf_wave_usedots)
  2272. {
  2273. lpDevice->DrawPrimitiveUP(D3DPT_POINTLIST, nBreak1, (void*)v1, sizeof(WFVERTEX));
  2274. lpDevice->DrawPrimitiveUP(D3DPT_POINTLIST, nVerts1-nBreak1, (void*)&v1[nBreak1], sizeof(WFVERTEX));
  2275. }
  2276. else
  2277. {
  2278. lpDevice->DrawPrimitiveUP(D3DPT_LINESTRIP, nBreak1-1, (void*)v1, sizeof(WFVERTEX));
  2279. lpDevice->DrawPrimitiveUP(D3DPT_LINESTRIP, nVerts1-nBreak1-1, (void*)&v1[nBreak1], sizeof(WFVERTEX));
  2280. }
  2281. }
  2282. }
  2283. }
  2284. lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
  2285. }
  2286. void CPlugin::DrawSprites()
  2287. {
  2288. LPDIRECT3DDEVICE9 lpDevice = GetDevice();
  2289. if (!lpDevice)
  2290. return;
  2291. lpDevice->SetTexture(0, NULL);
  2292. lpDevice->SetFVF( WFVERTEX_FORMAT );
  2293. if (*m_pState->var_pf_darken_center)
  2294. {
  2295. lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
  2296. lpDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);//SRCALPHA);
  2297. lpDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
  2298. WFVERTEX v3[6];
  2299. ZeroMemory(v3, sizeof(WFVERTEX)*6);
  2300. // colors:
  2301. v3[0].Diffuse = D3DCOLOR_RGBA_01(0, 0, 0, 3.0f/32.0f);
  2302. v3[1].Diffuse = D3DCOLOR_RGBA_01(0, 0, 0, 0.0f/32.0f);
  2303. v3[2].Diffuse = v3[1].Diffuse;
  2304. v3[3].Diffuse = v3[1].Diffuse;
  2305. v3[4].Diffuse = v3[1].Diffuse;
  2306. v3[5].Diffuse = v3[1].Diffuse;
  2307. // positioning:
  2308. float fHalfSize = 0.05f;
  2309. v3[0].x = 0.0f;
  2310. v3[1].x = 0.0f - fHalfSize*ASPECT;
  2311. v3[2].x = 0.0f;
  2312. v3[3].x = 0.0f + fHalfSize*ASPECT;
  2313. v3[4].x = 0.0f;
  2314. v3[5].x = v3[1].x;
  2315. v3[0].y = 0.0f;
  2316. v3[1].y = 0.0f;
  2317. v3[2].y = 0.0f - fHalfSize;
  2318. v3[3].y = 0.0f;
  2319. v3[4].y = 0.0f + fHalfSize;
  2320. v3[5].y = v3[1].y;
  2321. //v3[0].tu = 0; v3[1].tu = 1; v3[2].tu = 0; v3[3].tu = 1;
  2322. //v3[0].tv = 1; v3[1].tv = 1; v3[2].tv = 0; v3[3].tv = 0;
  2323. lpDevice->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 4, (LPVOID)v3, sizeof(WFVERTEX));
  2324. lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
  2325. }
  2326. // do borders
  2327. {
  2328. float fOuterBorderSize = (float)*m_pState->var_pf_ob_size;
  2329. float fInnerBorderSize = (float)*m_pState->var_pf_ib_size;
  2330. lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
  2331. lpDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
  2332. lpDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
  2333. for (int it=0; it<2; it++)
  2334. {
  2335. WFVERTEX v3[4];
  2336. ZeroMemory(v3, sizeof(WFVERTEX)*4);
  2337. // colors:
  2338. float r = (it==0) ? (float)*m_pState->var_pf_ob_r : (float)*m_pState->var_pf_ib_r;
  2339. float g = (it==0) ? (float)*m_pState->var_pf_ob_g : (float)*m_pState->var_pf_ib_g;
  2340. float b = (it==0) ? (float)*m_pState->var_pf_ob_b : (float)*m_pState->var_pf_ib_b;
  2341. float a = (it==0) ? (float)*m_pState->var_pf_ob_a : (float)*m_pState->var_pf_ib_a;
  2342. if (a > 0.001f)
  2343. {
  2344. v3[0].Diffuse = D3DCOLOR_RGBA_01(r,g,b,a);
  2345. v3[1].Diffuse = v3[0].Diffuse;
  2346. v3[2].Diffuse = v3[0].Diffuse;
  2347. v3[3].Diffuse = v3[0].Diffuse;
  2348. // positioning:
  2349. float fInnerRad = (it==0) ? 1.0f - fOuterBorderSize : 1.0f - fOuterBorderSize - fInnerBorderSize;
  2350. float fOuterRad = (it==0) ? 1.0f : 1.0f - fOuterBorderSize;
  2351. v3[0].x = fInnerRad;
  2352. v3[1].x = fOuterRad;
  2353. v3[2].x = fOuterRad;
  2354. v3[3].x = fInnerRad;
  2355. v3[0].y = fInnerRad;
  2356. v3[1].y = fOuterRad;
  2357. v3[2].y = -fOuterRad;
  2358. v3[3].y = -fInnerRad;
  2359. for (int rot=0; rot<4; rot++)
  2360. {
  2361. lpDevice->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, (LPVOID)v3, sizeof(WFVERTEX));
  2362. // rotate by 90 degrees
  2363. for (int v=0; v<4; v++)
  2364. {
  2365. float t = 1.570796327f;
  2366. float x = v3[v].x;
  2367. float y = v3[v].y;
  2368. v3[v].x = x*cosf(t) - y*sinf(t);
  2369. v3[v].y = x*sinf(t) + y*cosf(t);
  2370. }
  2371. }
  2372. }
  2373. }
  2374. lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
  2375. }
  2376. }
  2377. /*
  2378. bool CPlugin::SetMilkdropRenderTarget(LPDIRECTDRAWSURFACE7 lpSurf, int w, int h, char *szErrorMsg)
  2379. {
  2380. HRESULT hr = m_lpD3DDev->SetRenderTarget(lpSurf, 0);
  2381. if (hr != D3D_OK)
  2382. {
  2383. //if (szErrorMsg && szErrorMsg[0]) dumpmsg(szErrorMsg);
  2384. //IdentifyD3DError(hr);
  2385. return false;
  2386. }
  2387. //DDSURFACEDESC2 ddsd;
  2388. //ddsd.dwSize = sizeof(ddsd);
  2389. //lpSurf->GetSurfaceDesc(&ddsd);
  2390. D3DVIEWPORT7 viewData;
  2391. ZeroMemory(&viewData, sizeof(D3DVIEWPORT7));
  2392. viewData.dwWidth = w; // not: in windowed mode, when lpSurf is the back buffer, chances are good that w,h are smaller than the full surface size (since real size is fullscreen, but we're only using a portion of it as big as the window).
  2393. viewData.dwHeight = h;
  2394. hr = m_lpD3DDev->SetViewport(&viewData);
  2395. return true;
  2396. }
  2397. */
  2398. void CPlugin::DrawUserSprites() // from system memory, to back buffer.
  2399. {
  2400. #if 0
  2401. LPDIRECT3DDEVICE8 lpDevice = GetDevice();
  2402. if (!lpDevice)
  2403. return;
  2404. lpDevice->SetTexture(0, NULL);
  2405. lpDevice->SetVertexShader( SPRITEVERTEX_FORMAT );
  2406. lpDevice->SetRenderState(D3DRS_WRAP0, 0);
  2407. SetTextureStageState(0, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP);
  2408. SetTextureStageState(0, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP);
  2409. SetTextureStageState(0, D3DTSS_ADDRESSW, D3DTADDRESS_WRAP);
  2410. // reset these to the standard safe mode:
  2411. SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
  2412. SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_DIFFUSE);
  2413. SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_TEXTURE);
  2414. SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
  2415. SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );
  2416. SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE );
  2417. SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
  2418. /*
  2419. lpDevice->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_GOURAUD); //D3DSHADE_GOURAUD
  2420. lpDevice->SetRenderState(D3DRS_SPECULARENABLE, FALSE);
  2421. lpDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
  2422. if (m_D3DDevDesc.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_DITHER)
  2423. lpDevice->SetRenderState(D3DRS_DITHERENABLE, TRUE);
  2424. lpDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
  2425. lpDevice->SetRenderState(D3DRS_LIGHTING, FALSE);
  2426. lpDevice->SetRenderState(D3DRS_COLORVERTEX, TRUE);
  2427. lpDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID); // vs. wireframe
  2428. lpDevice->SetRenderState(D3DRS_AMBIENT, D3DCOLOR_RGBA_01(1,1,1,1));
  2429. SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTFG_LINEAR );
  2430. SetTextureStageState(0, D3DTSS_MINFILTER, D3DTFN_LINEAR );
  2431. SetTextureStageState(0, D3DTSS_MIPFILTER, D3DTFP_LINEAR );
  2432. */
  2433. for (int iSlot=0; iSlot < NUM_TEX; iSlot++)
  2434. {
  2435. if (m_texmgr.m_tex[iSlot].pSurface)
  2436. {
  2437. int k;
  2438. // set values of input variables:
  2439. *(m_texmgr.m_tex[iSlot].var_time) = (double)(GetTime() - m_texmgr.m_tex[iSlot].fStartTime);
  2440. *(m_texmgr.m_tex[iSlot].var_frame) = (double)(GetFrame() - m_texmgr.m_tex[iSlot].nStartFrame);
  2441. *(m_texmgr.m_tex[iSlot].var_fps) = (double)GetFps();
  2442. *(m_texmgr.m_tex[iSlot].var_progress) = (double)m_pState->m_fBlendProgress;
  2443. *(m_texmgr.m_tex[iSlot].var_bass) = (double)mysound.imm_rel[0];
  2444. *(m_texmgr.m_tex[iSlot].var_mid) = (double)mysound.imm_rel[1];
  2445. *(m_texmgr.m_tex[iSlot].var_treb) = (double)mysound.imm_rel[2];
  2446. *(m_texmgr.m_tex[iSlot].var_bass_att) = (double)mysound.avg_rel[0];
  2447. *(m_texmgr.m_tex[iSlot].var_mid_att) = (double)mysound.avg_rel[1];
  2448. *(m_texmgr.m_tex[iSlot].var_treb_att) = (double)mysound.avg_rel[2];
  2449. // evaluate expressions
  2450. #ifndef _NO_EXPR_
  2451. if (m_texmgr.m_tex[iSlot].m_codehandle)
  2452. {
  2453. resetVars(m_texmgr.m_tex[iSlot].m_vars);
  2454. executeCode(m_texmgr.m_tex[iSlot].m_codehandle);
  2455. resetVars(NULL);
  2456. }
  2457. #endif
  2458. bool bKillSprite = (*m_texmgr.m_tex[iSlot].var_done != 0.0);
  2459. bool bBurnIn = (*m_texmgr.m_tex[iSlot].var_burn != 0.0);
  2460. // Remember the original backbuffer and zbuffer
  2461. LPDIRECT3DSURFACE8 pBackBuffer, pZBuffer;
  2462. lpDevice->GetRenderTarget( &pBackBuffer );
  2463. lpDevice->GetDepthStencilSurface( &pZBuffer );
  2464. if (/*bKillSprite &&*/ bBurnIn)
  2465. {
  2466. // set up to render [from NULL] to VS1 (for burn-in).
  2467. lpDevice->SetTexture(0, NULL);
  2468. IDirect3DSurface8* pNewTarget = NULL;
  2469. if (m_lpVS[1]->GetSurfaceLevel(0, &pNewTarget) != D3D_OK)
  2470. return;
  2471. lpDevice->SetRenderTarget(pNewTarget, NULL);
  2472. pNewTarget->Release();
  2473. lpDevice->SetTexture(0, NULL);
  2474. }
  2475. // finally, use the results to draw the sprite.
  2476. if (lpDevice->SetTexture(0, m_texmgr.m_tex[iSlot].pSurface) != D3D_OK)
  2477. return;
  2478. SPRITEVERTEX v3[4];
  2479. ZeroMemory(v3, sizeof(SPRITEVERTEX)*4);
  2480. /*
  2481. int dest_w, dest_h;
  2482. {
  2483. LPDIRECT3DSURFACE8 pRT;
  2484. lpDevice->GetRenderTarget( &pRT );
  2485. D3DSURFACE_DESC desc;
  2486. pRT->GetDesc(&desc);
  2487. dest_w = desc.Width;
  2488. dest_h = desc.Height;
  2489. pRT->Release();
  2490. }*/
  2491. float x = min(1000.0f, max(-1000.0f, (float)(*m_texmgr.m_tex[iSlot].var_x) * 2.0f - 1.0f ));
  2492. float y = min(1000.0f, max(-1000.0f, (float)(*m_texmgr.m_tex[iSlot].var_y) * 2.0f - 1.0f ));
  2493. float sx = min(1000.0f, max(-1000.0f, (float)(*m_texmgr.m_tex[iSlot].var_sx) ));
  2494. float sy = min(1000.0f, max(-1000.0f, (float)(*m_texmgr.m_tex[iSlot].var_sy) ));
  2495. float rot = (float)(*m_texmgr.m_tex[iSlot].var_rot);
  2496. int flipx = (*m_texmgr.m_tex[iSlot].var_flipx == 0.0) ? 0 : 1;
  2497. int flipy = (*m_texmgr.m_tex[iSlot].var_flipy == 0.0) ? 0 : 1;
  2498. float repeatx = min(100.0f, max(0.01f, (float)(*m_texmgr.m_tex[iSlot].var_repeatx) ));
  2499. float repeaty = min(100.0f, max(0.01f, (float)(*m_texmgr.m_tex[iSlot].var_repeaty) ));
  2500. int blendmode = min(4, max(0, ((int)(*m_texmgr.m_tex[iSlot].var_blendmode))));
  2501. float r = min(1.0f, max(0.0f, ((float)(*m_texmgr.m_tex[iSlot].var_r))));
  2502. float g = min(1.0f, max(0.0f, ((float)(*m_texmgr.m_tex[iSlot].var_g))));
  2503. float b = min(1.0f, max(0.0f, ((float)(*m_texmgr.m_tex[iSlot].var_b))));
  2504. float a = min(1.0f, max(0.0f, ((float)(*m_texmgr.m_tex[iSlot].var_a))));
  2505. // set x,y coords
  2506. v3[0+flipx].x = -sx;
  2507. v3[1-flipx].x = sx;
  2508. v3[2+flipx].x = -sx;
  2509. v3[3-flipx].x = sx;
  2510. v3[0+flipy*2].y = -sy;
  2511. v3[1+flipy*2].y = -sy;
  2512. v3[2-flipy*2].y = sy;
  2513. v3[3-flipy*2].y = sy;
  2514. // first aspect ratio: adjust for non-1:1 images
  2515. {
  2516. float aspect = m_texmgr.m_tex[iSlot].img_h / (float)m_texmgr.m_tex[iSlot].img_w;
  2517. if (aspect < 1)
  2518. for (k=0; k<4; k++) v3[k].y *= aspect; // wide image
  2519. else
  2520. for (k=0; k<4; k++) v3[k].x /= aspect; // tall image
  2521. }
  2522. // 2D rotation
  2523. {
  2524. float cos_rot = cosf(rot);
  2525. float sin_rot = sinf(rot);
  2526. for (k=0; k<4; k++)
  2527. {
  2528. float x2 = v3[k].x*cos_rot - v3[k].y*sin_rot;
  2529. float y2 = v3[k].x*sin_rot + v3[k].y*cos_rot;
  2530. v3[k].x = x2;
  2531. v3[k].y = y2;
  2532. }
  2533. }
  2534. // translation
  2535. for (k=0; k<4; k++)
  2536. {
  2537. v3[k].x += x;
  2538. v3[k].y += y;
  2539. }
  2540. // second aspect ratio: normalize to width of screen
  2541. {
  2542. float aspect = GetWidth() / (float)(GetHeight());
  2543. if (aspect > 1)
  2544. for (k=0; k<4; k++) v3[k].y *= aspect;
  2545. else
  2546. for (k=0; k<4; k++) v3[k].x /= aspect;
  2547. }
  2548. // third aspect ratio: adjust for burn-in
  2549. if (bKillSprite && bBurnIn) // final render-to-VS1
  2550. {
  2551. float aspect = GetWidth()/(float)(GetHeight()*4.0f/3.0f);
  2552. if (aspect < 1.0f)
  2553. for (k=0; k<4; k++) v3[k].x *= aspect;
  2554. else
  2555. for (k=0; k<4; k++) v3[k].y /= aspect;
  2556. }
  2557. // finally, flip 'y' for annoying DirectX
  2558. //for (k=0; k<4; k++) v3[k].y *= -1.0f;
  2559. // set u,v coords
  2560. {
  2561. float dtu = 0.5f;// / (float)m_texmgr.m_tex[iSlot].tex_w;
  2562. float dtv = 0.5f;// / (float)m_texmgr.m_tex[iSlot].tex_h;
  2563. v3[0].tu = -dtu;
  2564. v3[1].tu = dtu;///*m_texmgr.m_tex[iSlot].img_w / (float)m_texmgr.m_tex[iSlot].tex_w*/ - dtu;
  2565. v3[2].tu = -dtu;
  2566. v3[3].tu = dtu;///*m_texmgr.m_tex[iSlot].img_w / (float)m_texmgr.m_tex[iSlot].tex_w*/ - dtu;
  2567. v3[0].tv = -dtv;
  2568. v3[1].tv = -dtv;
  2569. v3[2].tv = dtv;///*m_texmgr.m_tex[iSlot].img_h / (float)m_texmgr.m_tex[iSlot].tex_h*/ - dtv;
  2570. v3[3].tv = dtv;///*m_texmgr.m_tex[iSlot].img_h / (float)m_texmgr.m_tex[iSlot].tex_h*/ - dtv;
  2571. // repeat on x,y
  2572. for (k=0; k<4; k++)
  2573. {
  2574. v3[k].tu = (v3[k].tu - 0.0f)*repeatx + 0.5f;
  2575. v3[k].tv = (v3[k].tv - 0.0f)*repeaty + 0.5f;
  2576. }
  2577. }
  2578. // blendmodes src alpha: dest alpha:
  2579. // 0 blend r,g,b=modulate a=opacity SRCALPHA INVSRCALPHA
  2580. // 1 decal r,g,b=modulate a=modulate D3DBLEND_ONE D3DBLEND_ZERO
  2581. // 2 additive r,g,b=modulate a=modulate D3DBLEND_ONE D3DBLEND_ONE
  2582. // 3 srccolor r,g,b=no effect a=no effect SRCCOLOR INVSRCCOLOR
  2583. // 4 colorkey r,g,b=modulate a=no effect
  2584. switch(blendmode)
  2585. {
  2586. case 0:
  2587. default:
  2588. // alpha blend
  2589. /*
  2590. Q. I am rendering with alpha blending and setting the alpha
  2591. of the diffuse vertex component to determine the opacity.
  2592. It works when there is no texture set, but as soon as I set
  2593. a texture the alpha that I set is no longer applied. Why?
  2594. The problem originates in the texture blending stages, rather
  2595. than in the subsequent alpha blending. Alpha can come from
  2596. several possible sources. If this has not been specified,
  2597. then the alpha will be taken from the texture, if one is selected.
  2598. If no texture is selected, then the default will use the alpha
  2599. channel of the diffuse vertex component.
  2600. Explicitly specifying the diffuse vertex component as the source
  2601. for alpha will insure that the alpha is drawn from the alpha value
  2602. you set, whether a texture is selected or not:
  2603. pDevice->SetTextureStageState(D3DTSS_ALPHAOP,D3DTOP_SELECTARG1);
  2604. pDevice->SetTextureStageState(D3DTSS_ALPHAARG1,D3DTA_DIFFUSE);
  2605. If you later need to use the texture alpha as the source, set
  2606. D3DTSS_ALPHAARG1 to D3DTA_TEXTURE.
  2607. */
  2608. SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
  2609. SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE);
  2610. lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
  2611. lpDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
  2612. lpDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
  2613. for (k=0; k<4; k++) v3[k].Diffuse = D3DCOLOR_RGBA_01(r,g,b,a);
  2614. break;
  2615. case 1:
  2616. // decal
  2617. lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
  2618. //lpDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
  2619. //lpDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ZERO);
  2620. for (k=0; k<4; k++) v3[k].Diffuse = D3DCOLOR_RGBA_01(r*a,g*a,b*a,1);
  2621. break;
  2622. case 2:
  2623. // additive
  2624. lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
  2625. lpDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
  2626. lpDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
  2627. for (k=0; k<4; k++) v3[k].Diffuse = D3DCOLOR_RGBA_01(r*a,g*a,b*a,1);
  2628. break;
  2629. case 3:
  2630. // srccolor
  2631. lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
  2632. lpDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCCOLOR);
  2633. lpDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCCOLOR);
  2634. for (k=0; k<4; k++) v3[k].Diffuse = D3DCOLOR_RGBA_01(1,1,1,1);
  2635. break;
  2636. case 4:
  2637. // color keyed texture: use the alpha value in the texture to
  2638. // determine which texels get drawn.
  2639. /*lpDevice->SetRenderState(D3DRS_ALPHAREF, 0);
  2640. lpDevice->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_NOTEQUAL);
  2641. lpDevice->SetRenderState(D3DRS_ALPHATESTENABLE, TRUE);
  2642. */
  2643. SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
  2644. SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_DIFFUSE);
  2645. SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_TEXTURE);
  2646. SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
  2647. SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
  2648. SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE);
  2649. SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_TEXTURE);
  2650. SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
  2651. // also, smoothly blend this in-between texels:
  2652. lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
  2653. lpDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
  2654. lpDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
  2655. for (k=0; k<4; k++) v3[k].Diffuse = D3DCOLOR_RGBA_01(r,g,b,a);
  2656. break;
  2657. }
  2658. lpDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, (LPVOID)v3, sizeof(SPRITEVERTEX));
  2659. if (/*bKillSprite &&*/ bBurnIn) // final render-to-VS1
  2660. {
  2661. // Change the rendertarget back to the original setup
  2662. lpDevice->SetTexture(0, NULL);
  2663. lpDevice->SetRenderTarget( pBackBuffer, pZBuffer );
  2664. lpDevice->SetTexture(0, m_texmgr.m_tex[iSlot].pSurface);
  2665. // undo aspect ratio changes (that were used to fit it to VS1):
  2666. {
  2667. float aspect = GetWidth()/(float)(GetHeight()*4.0f/3.0f);
  2668. if (aspect < 1.0f)
  2669. for (k=0; k<4; k++) v3[k].x /= aspect;
  2670. else
  2671. for (k=0; k<4; k++) v3[k].y *= aspect;
  2672. }
  2673. lpDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, (LPVOID)v3, sizeof(SPRITEVERTEX));
  2674. }
  2675. SafeRelease(pBackBuffer);
  2676. SafeRelease(pZBuffer);
  2677. if (bKillSprite)
  2678. {
  2679. KillSprite(iSlot);
  2680. }
  2681. SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );
  2682. SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE );
  2683. SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
  2684. }
  2685. }
  2686. lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
  2687. // reset these to the standard safe mode:
  2688. SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
  2689. SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_DIFFUSE);
  2690. SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_TEXTURE);
  2691. SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
  2692. SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );
  2693. SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE );
  2694. SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
  2695. #endif
  2696. }
  2697. void CPlugin::ShowToUser(int bRedraw)
  2698. {
  2699. LPDIRECT3DDEVICE9 lpDevice = GetDevice();
  2700. if (!lpDevice)
  2701. return;
  2702. lpDevice->SetTexture(0, m_lpVS[1]);
  2703. lpDevice->SetFVF( SPRITEVERTEX_FORMAT );
  2704. lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
  2705. float fZoom = 1.0f;
  2706. SPRITEVERTEX v3[4];
  2707. ZeroMemory(v3, sizeof(SPRITEVERTEX)*4);
  2708. D3DRECT rect;
  2709. rect.x1 = m_posX;
  2710. rect.x2 = m_posX + GetWidth();
  2711. rect.y1 = m_posY;
  2712. rect.y2 = m_posY + GetHeight();
  2713. // WISO: lpDevice->SetScissors(1, false, &rect);
  2714. // extend the poly we draw by 1 pixel around the viewable image area,
  2715. // in case the video card wraps u/v coords with a +0.5-texel offset
  2716. // (otherwise, a 1-pixel-wide line of the image would wrap at the top and left edges).
  2717. /*
  2718. float fOnePlusInvWidth = 1.0f + 1.0f/(float)GetWidth();
  2719. float fOnePlusInvHeight = 1.0f + 1.0f/(float)GetHeight();
  2720. v3[0].x = -fOnePlusInvWidth;
  2721. v3[1].x = fOnePlusInvWidth;
  2722. v3[2].x = -fOnePlusInvWidth;
  2723. v3[3].x = fOnePlusInvWidth;
  2724. v3[0].y = fOnePlusInvHeight;
  2725. v3[1].y = fOnePlusInvHeight;
  2726. v3[2].y = -fOnePlusInvHeight;
  2727. v3[3].y = -fOnePlusInvHeight;
  2728. */
  2729. v3[0].x = ((m_posX / (float)m_backBufferWidth) * 2.0f) - 1.0f;
  2730. v3[1].x = (((m_posX + GetWidth()) / (float)m_backBufferWidth) * 2.0f) - 1.0f;
  2731. v3[2].x = v3[0].x;
  2732. v3[3].x = v3[1].x;
  2733. v3[0].y = (((m_posY + GetHeight()) / (float)m_backBufferHeight) * 2.0f) - 1.0f;
  2734. v3[1].y = v3[0].y;
  2735. v3[2].y = ((m_posY / (float)m_backBufferHeight) * 2.0f) - 1.0f;
  2736. v3[3].y = v3[2].y;
  2737. float aspect = (float)GetWidth() / (GetHeight() / ASPECT); // normal aspect in 1:1 pixels
  2738. aspect *= m_pixelRatio; // adjust for non-square TV pixels
  2739. float x_aspect_mult = 1.0f;
  2740. float y_aspect_mult = 1.0f;
  2741. if (aspect>1)
  2742. y_aspect_mult = aspect;
  2743. else
  2744. x_aspect_mult = 1.0f/aspect;
  2745. for (int n=0; n<4; n++)
  2746. {
  2747. v3[n].x *= x_aspect_mult;
  2748. v3[n].y *= y_aspect_mult;
  2749. }
  2750. float xRange = v3[1].x - v3[0].x;
  2751. float yRange = v3[0].y - v3[2].y;
  2752. if (m_pState->m_bRedBlueStereo || m_bAlways3D)
  2753. {
  2754. // red/blue stereo 3D
  2755. // NOTE: video echo is not yet supported.
  2756. // NOTE: gamma IS now supported (As of v1.04), but it's really slow.
  2757. // -no biggie though; 3d effect dies w/high gamma, so it won't get used beyond 2.0X.
  2758. float fGammaAdj = (float)*m_pState->var_pf_gamma;//m_pState->m_fGammaAdj.eval(GetTime());
  2759. int gamma_passes = (int)(fGammaAdj + 0.999f);
  2760. lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
  2761. for (int pass=0; pass<gamma_passes; pass++)
  2762. {
  2763. float colormult = min(1,max(0, (fGammaAdj-pass) )) / 255.0f;
  2764. for (int rep=0; rep<2; rep++)
  2765. {
  2766. int x, y;
  2767. int n = 0;
  2768. for (y=0; y<=m_nGridY; y++)
  2769. {
  2770. for (x=0; x<=m_nGridX; x++)
  2771. {
  2772. if (rep==0)
  2773. {
  2774. float du = fabsf((m_verts[n].x*0.5f + 0.5f) - m_verts[n].tu);
  2775. float dv = fabsf(0.5f - (m_verts[n].y*0.5f) - m_verts[n].tv);
  2776. //float mag_motion = sqrtf(m_verts[n].tu*m_verts[n].tu + m_verts[n].tv*m_verts[n].tv);
  2777. float mag_motion = sqrtf(du*du+dv*dv);
  2778. m_verts[n].tu = (m_verts[n].x*0.5f + 0.5f) + mag_motion*0.3f*m_fStereoSep;
  2779. //if (m_verts[n].tu < 0) m_verts[n].tu = 0;
  2780. //if (m_verts[n].tu > 1) m_verts[n].tu = 1;
  2781. }
  2782. else
  2783. {
  2784. //float du = fabsf((m_verts[n].x*0.5f + 0.5f) - m_verts[n].tu);
  2785. //float dv = fabsf(0.5f - (m_verts[n].y*0.5f) - m_verts[n].tv);
  2786. //float mag_motion = sqrtf(du*du+dv*dv);
  2787. //m_verts[n].tu = (m_verts[n].x*0.5f + 0.5f) - mag_motion*0.3f;
  2788. m_verts[n].tu = m_verts[n].x + 1.0f - m_verts[n].tu;
  2789. //if (m_verts[n].tu < 0) m_verts[n].tu = 0;
  2790. //if (m_verts[n].tu > 1) m_verts[n].tu = 1;
  2791. }
  2792. n++;
  2793. }
  2794. }
  2795. if (rep==0)
  2796. m_verts_temp[0].Diffuse = D3DCOLOR_RGBA_01(m_cRightEye3DColor[0]*colormult,m_cRightEye3DColor[1]*colormult,m_cRightEye3DColor[2]*colormult,1); // should be the color of right lens (~red)
  2797. else
  2798. m_verts_temp[0].Diffuse = D3DCOLOR_RGBA_01(m_cLeftEye3DColor[0]*colormult,m_cLeftEye3DColor[1]*colormult,m_cLeftEye3DColor[2]*colormult,1); // should be the color of left lens (~blue)
  2799. for (int poly=1; poly<m_nGridX+2; poly++)
  2800. m_verts_temp[poly].Diffuse = m_verts_temp[0].Diffuse;
  2801. for (int strip=0; strip<m_nGridY*2; strip++)
  2802. {
  2803. int index = strip * (m_nGridX+2);
  2804. for (int poly=0; poly<m_nGridX+2; poly++)
  2805. {
  2806. int ref_vert = m_indices[index];
  2807. m_verts_temp[poly].x = ((m_verts[ref_vert].x * 0.5f + 0.5f)) * xRange + v3[0].x;
  2808. m_verts_temp[poly].y = ((-m_verts[ref_vert].y * 0.5f + 0.5f)) * yRange + v3[2].y;
  2809. m_verts_temp[poly].z = m_verts[ref_vert].z;
  2810. m_verts_temp[poly].tu = m_verts[ref_vert].tu;
  2811. m_verts_temp[poly].tv = m_verts[ref_vert].tv;
  2812. // m_verts_temp[poly].x = m_verts[ref_vert].x*x_aspect_mult;
  2813. // m_verts_temp[poly].y = -m_verts[ref_vert].y*y_aspect_mult;
  2814. // m_verts_temp[poly].z = m_verts[ref_vert].z;
  2815. // m_verts_temp[poly].tu = m_verts[ref_vert].tu;
  2816. // m_verts_temp[poly].tv = m_verts[ref_vert].tv;
  2817. index++;
  2818. }
  2819. lpDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, m_nGridX, (void*)m_verts_temp, sizeof(SPRITEVERTEX));
  2820. }
  2821. lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
  2822. lpDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
  2823. lpDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
  2824. }
  2825. }
  2826. lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
  2827. }
  2828. else // regular display (non-stereo)
  2829. {
  2830. float shade[4][3] = {
  2831. { 1.0f, 1.0f, 1.0f },
  2832. { 1.0f, 1.0f, 1.0f },
  2833. { 1.0f, 1.0f, 1.0f },
  2834. { 1.0f, 1.0f, 1.0f } }; // for each vertex, then each comp.
  2835. float fShaderAmount = m_pState->m_fShader.eval(GetTime());
  2836. if (fShaderAmount > 0.001f)
  2837. {
  2838. for (int i=0; i<4; i++)
  2839. {
  2840. shade[i][0] = 0.6f + 0.3f*sinf(GetTime()*30.0f*0.0143f + 3 + i*21 + m_fRandStart[3]);
  2841. shade[i][1] = 0.6f + 0.3f*sinf(GetTime()*30.0f*0.0107f + 1 + i*13 + m_fRandStart[1]);
  2842. shade[i][2] = 0.6f + 0.3f*sinf(GetTime()*30.0f*0.0129f + 6 + i*9 + m_fRandStart[2]);
  2843. float max = ((shade[i][0] > shade[i][1]) ? shade[i][0] : shade[i][1]);
  2844. if (shade[i][2] > max) max = shade[i][2];
  2845. for (int k=0; k<3; k++)
  2846. {
  2847. shade[i][k] /= max;
  2848. shade[i][k] = 0.5f + 0.5f*shade[i][k];
  2849. }
  2850. for (int k=0; k<3; k++)
  2851. {
  2852. shade[i][k] = shade[i][k]*(fShaderAmount) + 1.0f*(1.0f - fShaderAmount);
  2853. }
  2854. v3[i].Diffuse = D3DCOLOR_RGBA_01(shade[i][0],shade[i][1],shade[i][2],1);
  2855. }
  2856. }
  2857. float fVideoEchoZoom = (float)(*m_pState->var_pf_echo_zoom);//m_pState->m_fVideoEchoZoom.eval(GetTime());
  2858. float fVideoEchoAlpha = (float)(*m_pState->var_pf_echo_alpha);//m_pState->m_fVideoEchoAlpha.eval(GetTime());
  2859. int nVideoEchoOrientation = (int) (*m_pState->var_pf_echo_orient) % 4;//m_pState->m_nVideoEchoOrientation;
  2860. float fGammaAdj = (float)(*m_pState->var_pf_gamma);//m_pState->m_fGammaAdj.eval(GetTime());
  2861. if (m_pState->m_bBlending &&
  2862. m_pState->m_fVideoEchoAlpha.eval(GetTime()) > 0.01f &&
  2863. m_pState->m_fVideoEchoAlphaOld > 0.01f &&
  2864. m_pState->m_nVideoEchoOrientation != m_pState->m_nVideoEchoOrientationOld)
  2865. {
  2866. if (m_pState->m_fBlendProgress < 0.5f)
  2867. {
  2868. nVideoEchoOrientation = m_pState->m_nVideoEchoOrientationOld;
  2869. fVideoEchoAlpha *= 1.0f - 2.0f*CosineInterp(m_pState->m_fBlendProgress);
  2870. }
  2871. else
  2872. {
  2873. fVideoEchoAlpha *= 2.0f*CosineInterp(m_pState->m_fBlendProgress) - 1.0f;
  2874. }
  2875. }
  2876. if (fVideoEchoAlpha > 0.001f)
  2877. {
  2878. // video echo
  2879. lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
  2880. lpDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
  2881. lpDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ZERO);
  2882. for (int i=0; i<2; i++)
  2883. {
  2884. fZoom = (i==0) ? 1.0f : fVideoEchoZoom;
  2885. float temp_lo = (0.5f - 0.5f/fZoom) + 0.5f / m_nTexSize;
  2886. float temp_hi = (0.5f + 0.5f/fZoom) + 0.5f / m_nTexSize;
  2887. v3[0].tu = temp_lo;
  2888. v3[0].tv = temp_hi;
  2889. v3[1].tu = temp_hi;
  2890. v3[1].tv = temp_hi;
  2891. v3[2].tu = temp_lo;
  2892. v3[2].tv = temp_lo;
  2893. v3[3].tu = temp_hi;
  2894. v3[3].tv = temp_lo;
  2895. // flipping
  2896. if (i==1)
  2897. {
  2898. for (int j=0; j<4; j++)
  2899. {
  2900. if (nVideoEchoOrientation % 2)
  2901. v3[j].tu = 1.0f - v3[j].tu;
  2902. if (nVideoEchoOrientation >= 2)
  2903. v3[j].tv = 1.0f - v3[j].tv;
  2904. }
  2905. }
  2906. float mix = (i==1) ? fVideoEchoAlpha : 1.0f - fVideoEchoAlpha;
  2907. for (int k=0; k<4; k++)
  2908. v3[k].Diffuse = D3DCOLOR_RGBA_01(mix*shade[k][0],mix*shade[k][1],mix*shade[k][2],1);
  2909. lpDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, (void*)v3, sizeof(SPRITEVERTEX));
  2910. if (i==0)
  2911. {
  2912. lpDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
  2913. lpDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
  2914. }
  2915. if (fGammaAdj > 0.001f)
  2916. {
  2917. // draw layer 'i' a 2nd (or 3rd, or 4th...) time, additively
  2918. int nRedraws = (int)(fGammaAdj - 0.0001f);
  2919. float gamma;
  2920. for (int nRedraw=0; nRedraw < nRedraws; nRedraw++)
  2921. {
  2922. if (nRedraw == nRedraws-1)
  2923. gamma = fGammaAdj - (int)(fGammaAdj - 0.0001f);
  2924. else
  2925. gamma = 1.0f;
  2926. for (int k=0; k<4; k++)
  2927. v3[k].Diffuse = D3DCOLOR_RGBA_01(gamma*mix*shade[k][0],gamma*mix*shade[k][1],gamma*mix*shade[k][2],1);
  2928. lpDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, (void*)v3, sizeof(SPRITEVERTEX));
  2929. }
  2930. }
  2931. }
  2932. }
  2933. else
  2934. {
  2935. // no video echo
  2936. v3[0].tu = 0.5f / m_nTexSize; v3[1].tu = 1; v3[2].tu = 0.5f / m_nTexSize; v3[3].tu = 1;
  2937. v3[0].tv = 1; v3[1].tv = 1; v3[2].tv = 0.5f / m_nTexSize; v3[3].tv = 0.5f / m_nTexSize;
  2938. lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
  2939. lpDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
  2940. lpDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ZERO);
  2941. // draw it iteratively, solid the first time, and additively after that
  2942. int nPasses = (int)(fGammaAdj - 0.001f) + 1;
  2943. float gamma;
  2944. for (int nPass=0; nPass < nPasses; nPass++)
  2945. {
  2946. if (nPass == nPasses - 1)
  2947. gamma = fGammaAdj - (float)nPass;
  2948. else
  2949. gamma = 1.0f;
  2950. for (int k=0; k<4; k++)
  2951. v3[k].Diffuse = D3DCOLOR_RGBA_01(gamma*shade[k][0],gamma*shade[k][1],gamma*shade[k][2],1);
  2952. lpDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, (void*)v3, sizeof(SPRITEVERTEX));
  2953. if (nPass==0)
  2954. {
  2955. lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
  2956. lpDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
  2957. lpDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
  2958. }
  2959. }
  2960. }
  2961. /*
  2962. SPRITEVERTEX v3[4];
  2963. ZeroMemory(v3, sizeof(SPRITEVERTEX)*4);
  2964. float fOnePlusInvWidth = 1.0f + 1.0f/(float)GetWidth();
  2965. float fOnePlusInvHeight = 1.0f + 1.0f/(float)GetHeight();
  2966. v3[0].x = -fOnePlusInvWidth;
  2967. v3[1].x = fOnePlusInvWidth;
  2968. v3[2].x = -fOnePlusInvWidth;
  2969. v3[3].x = fOnePlusInvWidth;
  2970. v3[0].y = fOnePlusInvHeight;
  2971. v3[1].y = fOnePlusInvHeight;
  2972. v3[2].y = -fOnePlusInvHeight;
  2973. v3[3].y = -fOnePlusInvHeight;
  2974. */
  2975. for (int i=0; i<4; i++) v3[i].Diffuse = D3DCOLOR_RGBA_01(1,1,1,1);
  2976. if (*m_pState->var_pf_brighten &&
  2977. (GetCaps()->SrcBlendCaps & D3DPBLENDCAPS_INVDESTCOLOR ) &&
  2978. (GetCaps()->DestBlendCaps & D3DPBLENDCAPS_DESTCOLOR)
  2979. )
  2980. {
  2981. // square root filter
  2982. //lpDevice->SetRenderState(D3DRS_COLORVERTEX, FALSE); //?
  2983. //lpDevice->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_FLAT); //?
  2984. lpDevice->SetTexture(0, NULL);
  2985. lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
  2986. // first, a perfect invert
  2987. lpDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_INVDESTCOLOR);
  2988. lpDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ZERO);
  2989. lpDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, (void*)v3, sizeof(SPRITEVERTEX));
  2990. // then modulate by self (square it)
  2991. lpDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ZERO);
  2992. lpDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_DESTCOLOR);
  2993. lpDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, (void*)v3, sizeof(SPRITEVERTEX));
  2994. // then another perfect invert
  2995. lpDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_INVDESTCOLOR);
  2996. lpDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ZERO);
  2997. lpDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, (void*)v3, sizeof(SPRITEVERTEX));
  2998. }
  2999. if (*m_pState->var_pf_darken &&
  3000. (GetCaps()->DestBlendCaps & D3DPBLENDCAPS_DESTCOLOR)
  3001. )
  3002. {
  3003. // squaring filter
  3004. //lpDevice->SetRenderState(D3DRS_COLORVERTEX, FALSE); //?
  3005. //lpDevice->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_FLAT); //?
  3006. lpDevice->SetTexture(0, NULL);
  3007. lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
  3008. lpDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ZERO);
  3009. lpDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_DESTCOLOR);
  3010. lpDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, (void*)v3, sizeof(SPRITEVERTEX));
  3011. //lpDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_DESTCOLOR);
  3012. //lpDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
  3013. //lpDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, (void*)v3, sizeof(SPRITEVERTEX));
  3014. }
  3015. if (*m_pState->var_pf_solarize &&
  3016. (GetCaps()->SrcBlendCaps & D3DPBLENDCAPS_DESTCOLOR ) &&
  3017. (GetCaps()->DestBlendCaps & D3DPBLENDCAPS_INVDESTCOLOR)
  3018. )
  3019. {
  3020. //lpDevice->SetRenderState(D3DRS_COLORVERTEX, FALSE); //?
  3021. //lpDevice->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_FLAT); //?
  3022. lpDevice->SetTexture(0, NULL);
  3023. lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
  3024. lpDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ZERO);
  3025. lpDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVDESTCOLOR);
  3026. lpDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, (void*)v3, sizeof(SPRITEVERTEX));
  3027. lpDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_DESTCOLOR);
  3028. lpDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
  3029. lpDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, (void*)v3, sizeof(SPRITEVERTEX));
  3030. }
  3031. if (*m_pState->var_pf_invert &&
  3032. (GetCaps()->SrcBlendCaps & D3DPBLENDCAPS_INVDESTCOLOR )
  3033. )
  3034. {
  3035. //lpDevice->SetRenderState(D3DRS_COLORVERTEX, FALSE); //?
  3036. //lpDevice->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_FLAT); //?
  3037. lpDevice->SetTexture(0, NULL);
  3038. lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
  3039. lpDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_INVDESTCOLOR);
  3040. lpDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ZERO);
  3041. lpDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, (void*)v3, sizeof(SPRITEVERTEX));
  3042. }
  3043. lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
  3044. }
  3045. }
  3046. void CPlugin::ShowSongTitleAnim(int w, int h, float fProgress)
  3047. {
  3048. #if 0
  3049. int i,x,y;
  3050. if (!m_lpDDSTitle) // this *can* be NULL, if not much video mem!
  3051. return;
  3052. LPDIRECT3DDEVICE8 lpDevice = GetDevice();
  3053. if (!lpDevice)
  3054. return;
  3055. lpDevice->SetTexture(0, m_lpDDSTitle);
  3056. lpDevice->SetVertexShader( SPRITEVERTEX_FORMAT );
  3057. lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
  3058. lpDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
  3059. lpDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
  3060. SPRITEVERTEX v3[128];
  3061. ZeroMemory(v3, sizeof(SPRITEVERTEX)*128);
  3062. if (m_supertext.bIsSongTitle)
  3063. {
  3064. // positioning:
  3065. float fSizeX = 50.0f / (float)m_supertext.nFontSizeUsed * powf(1.5f, m_supertext.fFontSize - 2.0f);
  3066. float fSizeY = fSizeX * m_nTitleTexSizeY/(float)m_nTitleTexSizeX;// * m_nWidth/(float)m_nHeight;
  3067. if (fSizeX > 0.88f)
  3068. {
  3069. fSizeY *= 0.88f/fSizeX;
  3070. fSizeX = 0.88f;
  3071. }
  3072. //fixme
  3073. if (fProgress < 1.0f)//(w!=h) // regular render-to-backbuffer
  3074. {
  3075. float aspect = w/(float)(h*4.0f/3.0f);
  3076. fSizeY *= aspect;
  3077. }
  3078. else // final render-to-VS0
  3079. {
  3080. float aspect = GetWidth()/(float)(GetHeight()*4.0f/3.0f);
  3081. if (aspect < 1.0f)
  3082. {
  3083. fSizeX *= aspect;
  3084. fSizeY *= aspect;
  3085. }
  3086. }
  3087. //if (fSizeX > 0.92f) fSizeX = 0.92f;
  3088. //if (fSizeY > 0.92f) fSizeY = 0.92f;
  3089. i = 0;
  3090. float vert_clip = VERT_CLIP;//1.0f;//0.45f; // warning: visible clipping has been observed at 0.4!
  3091. for (y=0; y<8; y++)
  3092. {
  3093. for (x=0; x<16; x++)
  3094. {
  3095. v3[i].tu = x/15.0f;
  3096. v3[i].tv = (y/7.0f - 0.5f)*vert_clip + 0.5f;
  3097. v3[i].x = (v3[i].tu*2.0f - 1.0f)*fSizeX;
  3098. v3[i].y = (v3[i].tv*2.0f - 1.0f)*fSizeY;
  3099. i++;
  3100. }
  3101. }
  3102. // warping
  3103. float ramped_progress = max(0.0f, 1-fProgress*1.5f);
  3104. float t2 = powf(ramped_progress, 1.8f)*1.3f;
  3105. for (y=0; y<8; y++)
  3106. {
  3107. for (x=0; x<16; x++)
  3108. {
  3109. i = y*16+x;
  3110. v3[i].x += t2*0.070f*sinf(GetTime()*0.31f + v3[i].x*0.39f - v3[i].y*1.94f);
  3111. v3[i].x += t2*0.044f*sinf(GetTime()*0.81f - v3[i].x*1.91f + v3[i].y*0.27f);
  3112. v3[i].x += t2*0.061f*sinf(GetTime()*1.31f + v3[i].x*0.61f + v3[i].y*0.74f);
  3113. v3[i].y += t2*0.061f*sinf(GetTime()*0.37f + v3[i].x*1.83f + v3[i].y*0.69f);
  3114. v3[i].y += t2*0.070f*sinf(GetTime()*0.67f + v3[i].x*0.42f - v3[i].y*1.39f);
  3115. v3[i].y += t2*0.087f*sinf(GetTime()*1.07f + v3[i].x*3.55f + v3[i].y*0.89f);
  3116. }
  3117. }
  3118. // scale down over time
  3119. float scale = 1.01f/(powf(fProgress, 0.21f) + 0.01f);
  3120. for (i=0; i<128; i++)
  3121. {
  3122. v3[i].x *= scale;
  3123. v3[i].y *= scale;
  3124. }
  3125. }
  3126. else
  3127. {
  3128. // positioning:
  3129. float fSizeX = (float)m_nTexSize/1024.0f * 100.0f / (float)m_supertext.nFontSizeUsed * powf(1.033f, m_supertext.fFontSize - 50.0f);
  3130. float fSizeY = fSizeX * m_nTitleTexSizeY/(float)m_nTitleTexSizeX;
  3131. //fixme
  3132. if (fProgress < 1.0f)//w!=h) // regular render-to-backbuffer
  3133. {
  3134. float aspect = w/(float)(h*4.0f/3.0f);
  3135. fSizeY *= aspect;
  3136. }
  3137. else // final render-to-VS0
  3138. {
  3139. float aspect = GetWidth()/(float)(GetHeight()*4.0f/3.0f);
  3140. if (aspect < 1.0f)
  3141. {
  3142. fSizeX *= aspect;
  3143. fSizeY *= aspect;
  3144. }
  3145. }
  3146. //if (fSize > 0.92f) fSize = 0.92f;
  3147. i = 0;
  3148. float vert_clip = VERT_CLIP;//0.67f; // warning: visible clipping has been observed at 0.5 (for very short strings) and even 0.6 (for wingdings)!
  3149. for (y=0; y<8; y++)
  3150. {
  3151. for (x=0; x<16; x++)
  3152. {
  3153. v3[i].tu = x/15.0f;
  3154. v3[i].tv = (y/7.0f - 0.5f)*vert_clip + 0.5f;
  3155. v3[i].x = (v3[i].tu*2.0f - 1.0f)*fSizeX;
  3156. v3[i].y = (v3[i].tv*2.0f - 1.0f)*fSizeY;
  3157. i++;
  3158. }
  3159. }
  3160. // apply 'growth' factor and move to user-specified (x,y)
  3161. //if (fabsf(m_supertext.fGrowth-1.0f) > 0.001f)
  3162. {
  3163. float t = (1.0f)*(1-fProgress) + (fProgress)*(m_supertext.fGrowth);
  3164. float dx = (m_supertext.fX*2-1);
  3165. float dy = (m_supertext.fY*2-1);
  3166. if (w!=h) // regular render-to-backbuffer
  3167. {
  3168. float aspect = w/(float)(h*4.0f/3.0f);
  3169. if (aspect < 1)
  3170. dx /= aspect;
  3171. else
  3172. dy *= aspect;
  3173. }
  3174. for (i=0; i<128; i++)
  3175. {
  3176. // note: (x,y) are in (-1,1) range, but m_supertext.f{X|Y} are in (0..1) range
  3177. v3[i].x = (v3[i].x)*t + dx;
  3178. v3[i].y = (v3[i].y)*t + dy;
  3179. }
  3180. }
  3181. }
  3182. WORD indices[7*15*6];
  3183. i = 0;
  3184. for (y=0; y<7; y++)
  3185. {
  3186. for (x=0; x<15; x++)
  3187. {
  3188. indices[i++] = y*16 + x;
  3189. indices[i++] = y*16 + x + 1;
  3190. indices[i++] = y*16 + x + 16;
  3191. indices[i++] = y*16 + x + 1;
  3192. indices[i++] = y*16 + x + 16;
  3193. indices[i++] = y*16 + x + 17;
  3194. }
  3195. }
  3196. // final flip on y
  3197. //for (i=0; i<128; i++)
  3198. // v3[i].y *= -1.0f;
  3199. for (i=0; i<128; i++)
  3200. v3[i].y /= ASPECT;
  3201. for (int it=0; it<2; it++)
  3202. {
  3203. // colors
  3204. {
  3205. float t;
  3206. if (m_supertext.bIsSongTitle)
  3207. t = powf(fProgress, 0.3f)*1.0f;
  3208. else
  3209. t = CosineInterp(min(1.0f, (fProgress/m_supertext.fFadeTime)));
  3210. if (it==0)
  3211. v3[0].Diffuse = D3DCOLOR_RGBA_01(t,t,t,t);
  3212. else
  3213. v3[0].Diffuse = D3DCOLOR_RGBA_01(t*m_supertext.nColorR/255.0f,t*m_supertext.nColorG/255.0f,t*m_supertext.nColorB/255.0f,t);
  3214. for (i=1; i<128; i++)
  3215. v3[i].Diffuse = v3[0].Diffuse;
  3216. }
  3217. // nudge down & right for shadow, up & left for solid text
  3218. float offset_x = 0, offset_y = 0;
  3219. switch(it)
  3220. {
  3221. case 0:
  3222. offset_x = 2.0f/(float)m_nTitleTexSizeX;
  3223. offset_y = 2.0f/(float)m_nTitleTexSizeY;
  3224. break;
  3225. case 1:
  3226. offset_x = -4.0f/(float)m_nTitleTexSizeX;
  3227. offset_y = -4.0f/(float)m_nTitleTexSizeY;
  3228. break;
  3229. }
  3230. for (i=0; i<128; i++)
  3231. {
  3232. v3[i].x += offset_x;
  3233. v3[i].y += offset_y;
  3234. }
  3235. if (it == 0)
  3236. {
  3237. lpDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ZERO);//SRCALPHA);
  3238. lpDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCCOLOR);
  3239. }
  3240. else
  3241. {
  3242. lpDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);//SRCALPHA);
  3243. lpDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
  3244. }
  3245. lpDevice->DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST, 0, 128, 15*7*6/3, indices, D3DFMT_INDEX16, v3, sizeof(SPRITEVERTEX));
  3246. }
  3247. lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
  3248. #endif
  3249. }