raster.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795
  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Scan UI
  4. //
  5. //////////////////////////////////////////////////////////////////////////////
  6. #include "pch.h"
  7. //////////////////////////////////////////////////////////////////////////////
  8. //
  9. // !!!
  10. //
  11. //////////////////////////////////////////////////////////////////////////////
  12. // translate the verticies to eye space
  13. // light the verticies
  14. // ?? how does opengl handle lights with attenuation
  15. // form triangles
  16. // clip triangles
  17. // perspective project triangles
  18. // do setup
  19. // fill
  20. // modulated
  21. // can just modulate palette
  22. // perspective correct
  23. // do divide every 16 pixels
  24. // texture
  25. // 16bpp
  26. //////////////////////////////////////////////////////////////////////////////
  27. //
  28. // The main entry point
  29. //
  30. //////////////////////////////////////////////////////////////////////////////
  31. #include "main.h"
  32. //////////////////////////////////////////////////////////////////////////////
  33. //
  34. // Fixed Point Macros
  35. //
  36. //////////////////////////////////////////////////////////////////////////////
  37. inline int MakeFixed(float x) { return int(x * 65536); }
  38. //////////////////////////////////////////////////////////////////////////////
  39. //
  40. // The main entry point
  41. //
  42. //////////////////////////////////////////////////////////////////////////////
  43. class Color {
  44. public:
  45. DWORD m_r, m_g, m_b;
  46. Color(DWORD r, DWORD g, DWORD b) :
  47. m_r(r),
  48. m_g(g),
  49. m_b(b)
  50. {
  51. }
  52. };
  53. class SVertex {
  54. public:
  55. float m_x, m_y, m_z, m_qw, m_uqw, m_vqw;
  56. SVertex(float x, float y, float z, float qw, float u, float v) :
  57. m_x(x),
  58. m_y(y),
  59. m_z(z),
  60. m_qw(qw),
  61. m_uqw(u * qw),
  62. m_vqw(v * qw)
  63. {}
  64. };
  65. //////////////////////////////////////////////////////////////////////////////
  66. //
  67. // Scan Window
  68. //
  69. //////////////////////////////////////////////////////////////////////////////
  70. const WORD Black565 = 0x0000;
  71. const WORD White565 = 0xffff;
  72. const WORD Blue565 = 0x001f;
  73. const WORD Red565 = 0xf800;
  74. const WORD Green565 = 0x07e0;
  75. const WORD Violet565 = Red565 | Blue565;
  76. const WORD Yellow565 = Red565 | Green565;
  77. const WORD Cyan565 = Green565 | Blue565;
  78. WORD g_pcolor[] =
  79. {
  80. Black565, // 0
  81. White565, // 1
  82. Red565, // 2
  83. Green565, // 3
  84. Blue565, // 4
  85. Violet565, // 5
  86. Yellow565, // 6
  87. Cyan565 // 7
  88. };
  89. BYTE g_ptexture[] =
  90. {
  91. 4, 4, 4, 4, 4, 4, 4, 4,
  92. 4, 0, 1, 0, 1, 0, 1, 4,
  93. 4, 1, 3, 2, 3, 2, 0, 4,
  94. 4, 0, 2, 5, 6, 3, 1, 4,
  95. 4, 1, 3, 6, 5, 2, 0, 4,
  96. 4, 0, 2, 3, 2, 3, 1, 4,
  97. 4, 1, 0, 1, 0, 1, 0, 4,
  98. 4, 4, 4, 4, 4, 4, 4, 4
  99. };
  100. class ScanWindow : public AnimationWindow {
  101. protected:
  102. float m_pixels;
  103. float m_lastTime;
  104. BYTE* m_pdata;
  105. DWORD m_pitch;
  106. WORD* m_pcolors;
  107. BYTE* m_ptexture;
  108. DWORD m_texturePitch;
  109. // plane deltas
  110. float m_dqwdx;
  111. float m_dqwdy;
  112. float m_duqwdx;
  113. float m_duqwdy;
  114. float m_dvqwdx;
  115. float m_dvqwdy;
  116. // edge deltas
  117. int m_xmin ;
  118. float m_xminFrac ;
  119. int m_dxmindyLittle;
  120. int m_dxmindyBig ;
  121. float m_dxmindyFrac ;
  122. int m_xmax ;
  123. float m_xmaxFrac ;
  124. int m_dxmaxdyLittle;
  125. int m_dxmaxdyBig ;
  126. float m_dxmaxdyFrac ;
  127. float m_qw;
  128. float m_dqwdyLittle;
  129. float m_dqwdyBig ;
  130. float m_uqw;
  131. float m_duqwdyLittle;
  132. float m_duqwdyBig;
  133. float m_vqw;
  134. float m_dvqwdyLittle;
  135. float m_dvqwdyBig;
  136. public:
  137. ScanWindow() :
  138. AnimationWindow(Rect(8, 28, 640, 480), "Scan"),
  139. m_lastTime(0)
  140. {
  141. }
  142. ~ScanWindow()
  143. {
  144. }
  145. //
  146. // Rendering Methods
  147. void FillTriangle(const SVertex& v0, const SVertex& v1, const SVertex& v2);
  148. void DeltaSetup(const SVertex& va, const SVertex& vb, const SVertex& vc);
  149. void CalcXMin(const SVertex& va, const SVertex& vb);
  150. void CalcXMax(const SVertex& va, const SVertex& vb);
  151. void FillSubTriangle(const SVertex& va, const SVertex& vb);
  152. void Render(float time) {
  153. m_psurface->FillRect(Rect(9, 9, 19, 19), ZColor(0, 0.5, 0));
  154. const DDSDescription& ddsd = m_psurface->GetDescription();
  155. m_pitch = ddsd.Pitch();
  156. m_pdata = (BYTE*)(m_psurface->GetPointer());
  157. m_pcolors = g_pcolor;
  158. m_ptexture = g_ptexture;
  159. m_texturePitch = 8;
  160. for (int index = 0; index < 1; index++) {
  161. /*
  162. {
  163. float x = 200 ;//+ 3 * sin(time);
  164. float qw0 = 0.5;
  165. float qw1 = 1;
  166. SVertex v0(x - qw0 * 100, 50, 0, qw0, 0, 0);
  167. SVertex v1(x - qw1 * 100, 250, 0, qw1, 0, 8);
  168. SVertex v2(x + qw1 * 100, 250, 0, qw1, 8, 8);
  169. SVertex v3(x + qw0 * 100, 50, 0, qw0, 8, 0);
  170. g_pcolor[4] = Blue565;
  171. FillTriangle(v0, v1, v2);
  172. g_pcolor[4] = Red565;
  173. FillTriangle(v0, v2, v3);
  174. }
  175. */
  176. {
  177. float xc = 200;// + 3 * sin(time);
  178. float yc = 150;
  179. float xsize = 100;
  180. float ysize = 100;
  181. float qw0 = 0.5;
  182. float qw1 = 1;
  183. SVertex v0(xc - xsize, yc - qw1 * ysize, 0, qw1, 0, 0);
  184. SVertex v1(xc - xsize, yc + qw1 * ysize, 0, qw1, 0, 8);
  185. SVertex v2(xc + xsize, yc + qw0 * ysize, 0, qw0, 8, 8);
  186. SVertex v3(xc + xsize, yc - qw0 * ysize, 0, qw0, 8, 0);
  187. g_pcolor[4] = Blue565;
  188. FillTriangle(v0, v1, v3);
  189. g_pcolor[4] = Red565;
  190. FillTriangle(v3, v1, v2);
  191. }
  192. /*
  193. {
  194. SVertex v0(x + 250 - 100, 50, 0, 1, 0, 0);
  195. SVertex v1(x + 250 - 100, 250, 0, 1, 0, 8);
  196. SVertex v2(x + 250 + 100, 250, 0, 1, 8, 8);
  197. SVertex v3(x + 250 + 100, 50, 0, 1, 8, 0);
  198. g_pcolor[4] = Blue565;
  199. FillTriangle(v0, v1, v2);
  200. g_pcolor[4] = Red565;
  201. FillTriangle(v0, v2, v3);
  202. }
  203. {
  204. SVertex v0(10, 10, 0, 1, 0, 0);
  205. SVertex v1(10, 18, 0, 1, 0, 8);
  206. SVertex v2(18, 18, 0, 1, 8, 8);
  207. SVertex v3(18, 10, 0, 1, 8, 0);
  208. g_pcolor[4] = Blue565;
  209. FillTriangle(v0, v1, v2);
  210. g_pcolor[4] = Red565;
  211. FillTriangle(v0, v2, v3);
  212. }
  213. */
  214. }
  215. m_psurface->ReleasePointer(m_pdata);
  216. }
  217. //
  218. // Animation Window methods
  219. //
  220. ZString GetFPSString(float dtime, float mspf, Context* pcontext)
  221. {
  222. ZString str =
  223. AnimationWindow::GetFPSString(dtime, mspf, pcontext) + " mps: " +
  224. ZString(m_pixels / (1000000 * dtime), 5, 2);
  225. m_pixels = 0;
  226. return str;
  227. }
  228. void DrawFrame(float time)
  229. {
  230. const float dtime = time - m_lastTime;
  231. m_lastTime = time;
  232. if (DoClear()) {
  233. m_psurface->FillSurface(ZColor(0.25, 0.25, 0.25));
  234. }
  235. if (DoDraw()) {
  236. Render(time);
  237. }
  238. }
  239. //
  240. // Window methods
  241. //
  242. bool OnMouseMessage(UINT message, UINT nFlags, const WinPoint& point)
  243. {
  244. switch (message) {
  245. case WM_LBUTTONDOWN:
  246. case WM_RBUTTONDOWN:
  247. return true;
  248. }
  249. return false;
  250. }
  251. DWORD WndProc(
  252. UINT message,
  253. WPARAM wParam,
  254. LPARAM lParam
  255. ) {
  256. switch (message) {
  257. case WM_CLOSE:
  258. PostQuitMessage(0);
  259. return 0;
  260. }
  261. return Window::WndProc(message, wParam, lParam);
  262. }
  263. };
  264. //////////////////////////////////////////////////////////////////////////////
  265. //
  266. // Scan Application
  267. //
  268. //////////////////////////////////////////////////////////////////////////////
  269. class ScanApp : public Win32App {
  270. protected:
  271. TRef<ScanWindow> m_papp;
  272. public:
  273. void Initialize()
  274. {
  275. m_papp = new ScanWindow();
  276. }
  277. } g_app;
  278. //////////////////////////////////////////////////////////////////////////////
  279. //
  280. //
  281. //
  282. //////////////////////////////////////////////////////////////////////////////
  283. template<int bits>
  284. class Fixed {
  285. protected:
  286. DWORD m_value;
  287. public:
  288. Fixed(float f) :
  289. m_value(f)
  290. {}
  291. Fixed(const Fixed& value) :
  292. m_value(value)
  293. {}
  294. void operator=(const Fixed& value)
  295. {
  296. m_value = value;
  297. }
  298. operator DWORD()
  299. {
  300. return m_value >> bits;
  301. }
  302. };
  303. //////////////////////////////////////////////////////////////////////////////
  304. //
  305. //
  306. //
  307. //////////////////////////////////////////////////////////////////////////////
  308. template<class Type>
  309. class Component {
  310. protected:
  311. Type m_value;
  312. Type m_dvalue;
  313. public:
  314. Component(Type value, Type dvalue) :
  315. m_value(value),
  316. m_dvalue(dvalue)
  317. {
  318. }
  319. operator Type()
  320. {
  321. return m_value;
  322. }
  323. void operator++()
  324. {
  325. m_value += m_dvalue;
  326. }
  327. };
  328. //////////////////////////////////////////////////////////////////////////////
  329. //
  330. //
  331. //
  332. //////////////////////////////////////////////////////////////////////////////
  333. void ScanWindow::FillTriangle(
  334. const SVertex& va,
  335. const SVertex& vb,
  336. const SVertex& vc
  337. ) {
  338. DeltaSetup(va, vb, vc);
  339. if (va.m_y == vc.m_y) {
  340. CalcXMin(va, vb);
  341. CalcXMax(vc, vb);
  342. FillSubTriangle(va, vb);
  343. } else if (vb.m_y == vc.m_y) {
  344. CalcXMin(va, vb);
  345. CalcXMax(va, vc);
  346. FillSubTriangle(va, vb);
  347. } else if (vb.m_y < vc.m_y) {
  348. CalcXMin(va, vb);
  349. CalcXMax(va, vc);
  350. FillSubTriangle(va, vb);
  351. CalcXMin(vb, vc);
  352. FillSubTriangle(vb, vc);
  353. } else {
  354. CalcXMin(va, vb);
  355. CalcXMax(va, vc);
  356. FillSubTriangle(va, vc);
  357. CalcXMax(vc, vb);
  358. FillSubTriangle(vc, vb);
  359. }
  360. }
  361. //////////////////////////////////////////////////////////////////////////////
  362. //
  363. //
  364. //
  365. //////////////////////////////////////////////////////////////////////////////
  366. void ScanWindow::DeltaSetup(
  367. const SVertex& va,
  368. const SVertex& vb,
  369. const SVertex& vc
  370. ) {
  371. float yab = vb.m_y - va.m_y;
  372. float yac = vc.m_y - va.m_y;
  373. float xab = vb.m_x - va.m_x;
  374. float xac = vc.m_x - va.m_x;
  375. float area = yab * xac - yac * xab;
  376. float qarea = 1 / area;
  377. m_pixels += area / 2;
  378. float yabn = yab * qarea;
  379. float yacn = yac * qarea;
  380. float xabn = xab * qarea;
  381. float xacn = xac * qarea;
  382. float qwab = vb.m_qw - va.m_qw;
  383. float qwac = vc.m_qw - va.m_qw;
  384. float uqwab = vb.m_uqw - va.m_uqw;
  385. float uqwac = vc.m_uqw - va.m_uqw;
  386. float vqwab = vb.m_vqw - va.m_vqw;
  387. float vqwac = vc.m_vqw - va.m_vqw;
  388. m_dqwdy = qwab * xacn - qwac * xabn;
  389. m_duqwdy = uqwab * xacn - uqwac * xabn;
  390. m_dvqwdy = vqwab * xacn - vqwac * xabn;
  391. m_dqwdx = qwac * yabn - qwab * yacn;
  392. m_duqwdx = uqwac * yabn - uqwab * yacn;
  393. m_dvqwdx = vqwac * yabn - vqwab * yacn;
  394. }
  395. //////////////////////////////////////////////////////////////////////////////
  396. //
  397. //
  398. //
  399. //////////////////////////////////////////////////////////////////////////////
  400. void ScanWindow::CalcXMin(
  401. const SVertex& va,
  402. const SVertex& vb
  403. ) {
  404. //
  405. // calculate ydelta
  406. //
  407. const int ymin = int(va.m_y + 0.5f);
  408. const float qdy = 1 / (vb.m_y - va.m_y);
  409. const float yDelta = (float(ymin) + 0.5f) - va.m_y;
  410. //
  411. // calculate dxmindy
  412. //
  413. const float dxmindy = (vb.m_x - va.m_x) * qdy;
  414. const float xminIntercept = va.m_x + dxmindy * yDelta + 0.5f;
  415. m_xmin = int(xminIntercept);
  416. const float xDelta = (float(m_xmin) + 0.5f) - va.m_x;
  417. if (dxmindy >= 0) {
  418. m_dxmindyLittle = int(dxmindy);
  419. m_dxmindyBig = m_dxmindyLittle + 1;
  420. m_dxmindyFrac = dxmindy - float(m_dxmindyLittle);
  421. m_xminFrac = xminIntercept - float(m_xmin) - 1;
  422. } else {
  423. m_dxmindyLittle = int(dxmindy);
  424. m_dxmindyBig = m_dxmindyLittle - 1;
  425. m_dxmindyFrac = float(m_dxmindyLittle) - dxmindy;
  426. m_xminFrac = float(m_xmin) - xminIntercept;
  427. }
  428. //
  429. // calculate qu, qv, and qw deltas
  430. //
  431. m_dqwdyLittle = m_dqwdy + m_dqwdx * m_dxmindyLittle;
  432. m_duqwdyLittle = m_duqwdy + m_duqwdx * m_dxmindyLittle;
  433. m_dvqwdyLittle = m_dvqwdy + m_dvqwdx * m_dxmindyLittle;
  434. if (m_dxmindyBig >= 0) {
  435. m_dqwdyBig = m_dqwdyLittle + m_dqwdx ;
  436. m_duqwdyBig = m_duqwdyLittle + m_duqwdx;
  437. m_dvqwdyBig = m_dvqwdyLittle + m_dvqwdx;
  438. } else {
  439. m_dqwdyBig = m_dqwdyLittle - m_dqwdx ;
  440. m_duqwdyBig = m_duqwdyLittle - m_duqwdx;
  441. m_dvqwdyBig = m_dvqwdyLittle - m_dvqwdx;
  442. }
  443. //
  444. // Initial values
  445. //
  446. m_qw = va.m_qw + m_dqwdy * yDelta + m_dqwdx * xDelta;
  447. m_uqw = va.m_uqw + m_duqwdy * yDelta + m_duqwdx * xDelta;
  448. m_vqw = va.m_vqw + m_dvqwdy * yDelta + m_dvqwdx * xDelta;
  449. ZAssert(m_qw >= 0);
  450. ZAssert(m_uqw >= 0);
  451. ZAssert(m_vqw >= 0);
  452. }
  453. //////////////////////////////////////////////////////////////////////////////
  454. //
  455. //
  456. //
  457. //////////////////////////////////////////////////////////////////////////////
  458. void ScanWindow::CalcXMax(
  459. const SVertex& va,
  460. const SVertex& vb
  461. ) {
  462. //
  463. // calculate ydelta
  464. //
  465. const int ymin = int(va.m_y + 0.5f);
  466. const float qdy = 1 / (vb.m_y - va.m_y);
  467. const float yDelta = (float(ymin) + 0.5f) - va.m_y;
  468. //
  469. // calculate dxmaxdy
  470. //
  471. const float dxmaxdy = (vb.m_x - va.m_x) * qdy;
  472. const float xmaxIntercept = va.m_x + dxmaxdy * yDelta + 0.5f;
  473. m_xmax = int(xmaxIntercept);
  474. if (dxmaxdy >= 0) {
  475. m_dxmaxdyLittle = int(dxmaxdy);
  476. m_dxmaxdyBig = m_dxmaxdyLittle + 1;
  477. m_dxmaxdyFrac = dxmaxdy - float(m_dxmaxdyLittle);
  478. m_xmaxFrac = xmaxIntercept - float(m_xmax) - 1;
  479. } else {
  480. m_dxmaxdyLittle = int(dxmaxdy);
  481. m_dxmaxdyBig = m_dxmaxdyLittle - 1;
  482. m_dxmaxdyFrac = float(m_dxmaxdyLittle) - dxmaxdy;
  483. m_xmaxFrac = float(m_xmax) - xmaxIntercept;
  484. }
  485. }
  486. //////////////////////////////////////////////////////////////////////////////
  487. //
  488. //
  489. //
  490. //////////////////////////////////////////////////////////////////////////////
  491. void ScanWindow::FillSubTriangle(
  492. const SVertex& va,
  493. const SVertex& vb
  494. ) {
  495. //
  496. // calculate y range
  497. //
  498. const int ymin = int(va.m_y + 0.5f);
  499. const int ymax = int(vb.m_y + 0.5f);
  500. //
  501. // copy stuff onto the stack
  502. //
  503. const WORD* pcolors = m_pcolors;
  504. const BYTE* ptexture = m_ptexture;
  505. const DWORD texturePitch = m_texturePitch;
  506. const DWORD pitch = m_pitch;
  507. const int dxmindyLittle = m_dxmindyLittle;
  508. const int dxmindyBig = m_dxmindyBig ;
  509. const float dxmindyFrac = m_dxmindyFrac ;
  510. const int dxmaxdyLittle = m_dxmaxdyLittle;
  511. const int dxmaxdyBig = m_dxmaxdyBig ;
  512. const float dxmaxdyFrac = m_dxmaxdyFrac ;
  513. const float dqwdx = m_dqwdx ;
  514. const float duqwdx = m_duqwdx ;
  515. const float dvqwdx = m_dvqwdx ;
  516. const float dqwdyLittle = m_dqwdyLittle ;
  517. const float duqwdyLittle = m_duqwdyLittle ;
  518. const float dvqwdyLittle = m_dvqwdyLittle ;
  519. const float dqwdyBig = m_dqwdyBig ;
  520. const float duqwdyBig = m_duqwdyBig ;
  521. const float dvqwdyBig = m_dvqwdyBig ;
  522. int xmin = m_xmin ;
  523. float xminFrac = m_xminFrac;
  524. int xmax = m_xmax ;
  525. float xmaxFrac = m_xmaxFrac;
  526. float qw = m_qw ;
  527. float uqw = m_uqw ;
  528. float vqw = m_vqw ;
  529. //
  530. // pixel format
  531. //
  532. const DWORD redMask = 0x1f << 11;
  533. const DWORD greenMask = 0x3f << 5;
  534. const DWORD blueMask = 0x1f;
  535. //
  536. // cubic approximation loop invariants
  537. //
  538. const float x1 = 0.25f;
  539. const float x2 = 0.90f;
  540. const float bd = 1 / (x1 * x1 - x1);
  541. const float btop = (x1 * x1 * x1 - x1);
  542. const float q = btop * bd;
  543. const float ad = x2 * x2 * x2 - q * x2 * x2 + (q - 1) * x2;
  544. //
  545. // fill the triangle
  546. //
  547. BYTE* pscan = m_pdata + ymin * pitch;
  548. for (int y = ymin; y < ymax; y++) {
  549. int count = xmax - xmin;
  550. if (count > 0) {
  551. BYTE* pdest = pscan + xmin * 2;
  552. // xdeltas
  553. const float xscale = float(count);
  554. const float g = 1 / xscale;
  555. const float g2 = g * g;
  556. const float g3 = g2 * g;
  557. // w values
  558. const float w0 = 1 / qw;
  559. const float w1 = 1 / (qw + dqwdx * xscale * x1);
  560. const float w2 = 1 / (qw + dqwdx * xscale * x2);
  561. const float w3 = 1 / (qw + dqwdx * xscale );
  562. // u values
  563. const float u0 = w0 * uqw;
  564. const float u3 = w3 * (uqw + duqwdx * xscale);
  565. const float uscale = u3 - u0;
  566. const float quscale = 1 / uscale;
  567. const float u1 = quscale * (w1 * (uqw + duqwdx * xscale * x1) - u0);
  568. const float u2 = quscale * (w2 * (uqw + duqwdx * xscale * x2) - u0);
  569. const float ru = (u1 - x1) * bd;
  570. const float au = (u2 - ru * x2 * x2 + (ru - 1) * x2) * ad;
  571. const float bu = (u1 - au * btop - x1) * bd;
  572. const float cu = 1 - au - bu;
  573. const float dddu = uscale * (au * 12 * g3 );
  574. float ddu = uscale * (au * 6 * g3 + bu * 2 * g2 );
  575. float du = uscale * (au * g3 + bu * g2 + cu * g);
  576. float u = u0;
  577. // v values
  578. const float v0 = w0 * vqw;
  579. const float v3 = w3 * (vqw + dvqwdx * xscale);
  580. const float vscale = v3 - v0;
  581. const float qvscale = 1 / vscale;
  582. const float v1 = qvscale * (w1 * (vqw + dvqwdx * xscale * x1) - v0);
  583. const float v2 = qvscale * (w2 * (vqw + dvqwdx * xscale * x2) - v0);
  584. const float rv = (v1 - x1) * bd;
  585. const float av = (v2 - rv * x2 * x2 + (rv - 1) * x2) * ad;
  586. const float bv = (v1 - av * btop - x1) * bd;
  587. const float cv = 1 - av - bv;
  588. const float dddv = vscale * (av * 12 * g3 );
  589. float ddv = vscale * (av * 6 * g3 + bv * 2 * g2 );
  590. float dv = vscale * (av * g3 + bv * g2 + cv * g);
  591. float v = v0;
  592. // x loop
  593. for(; count > 0; count--) {
  594. DWORD index = ptexture[int(v) * texturePitch + int(u)];
  595. *(WORD*)pdest = pcolors[index];
  596. //*(WORD*)pdest += 0x4;
  597. // x++
  598. pdest += 2;
  599. u += du;
  600. du += ddu;
  601. ddu += dddu;
  602. v += dv;
  603. dv += ddv;
  604. ddv += dddv;
  605. }
  606. }
  607. // y++
  608. pscan += pitch;
  609. xminFrac += dxmindyFrac;
  610. if (xminFrac >= 0) {
  611. xminFrac -= 1;
  612. xmin += dxmindyBig;
  613. qw += dqwdyBig;
  614. uqw += duqwdyBig;
  615. vqw += dvqwdyBig;
  616. } else {
  617. xmin += dxmindyLittle;
  618. qw += dqwdyLittle;
  619. uqw += duqwdyLittle;
  620. vqw += dvqwdyLittle;
  621. }
  622. xmaxFrac += dxmaxdyFrac;
  623. if (xmaxFrac >= 0) {
  624. xmaxFrac -= 1;
  625. xmax += dxmaxdyBig;
  626. } else {
  627. xmax += dxmaxdyLittle;
  628. }
  629. }
  630. //
  631. // Save the left hand values for the next part of the triangle
  632. //
  633. m_xmin = xmin ;
  634. m_xminFrac = xminFrac;
  635. m_xmax = xmax ;
  636. m_xmaxFrac = xmaxFrac;
  637. m_qw = qw ;
  638. m_uqw = uqw ;
  639. m_vqw = vqw ;
  640. }