Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

362 lines
13 KiB

  1. /*============================================================================
  2. *
  3. * Copyright (C) 1999-2000 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: bezier.cpp
  6. * Content: Implementation for Beziers
  7. *
  8. ****************************************************************************/
  9. #include "pch.cpp"
  10. #pragma hdrstop
  11. //-----------------------------------------------------------------------------
  12. // RefDev::ProcessBezier
  13. //-----------------------------------------------------------------------------
  14. HRESULT RefDev::ProcessBezier( DWORD dwOffW, DWORD dwOffH,
  15. DWORD dwWidth, DWORD dwHeight,
  16. DWORD dwStride, DWORD order,
  17. FLOAT *pPrimSegments,
  18. bool bDegenerate )
  19. {
  20. if(order == 0)
  21. {
  22. order = 2;
  23. }
  24. else
  25. {
  26. ++order;
  27. }
  28. if(((dwWidth - 1) % (order - 1)) != 0 || ((dwHeight - 1) % (order - 1)) != 0)
  29. {
  30. DPFERR("Incorrect order specified for current width or height");
  31. return DDERR_INVALIDPARAMS;
  32. }
  33. RDBezier bz(order, order);
  34. static const unsigned M[4] = {0, 0, 0, 0}, N[4] = {0, 0, 0, 0};
  35. unsigned u_segs, v_segs, u_start, v_start;
  36. if(pPrimSegments != 0)
  37. {
  38. u_segs = unsigned(double(unsigned(pPrimSegments[0]) + unsigned(pPrimSegments[2])) / 2.0 + 0.5);
  39. v_segs = unsigned(double(unsigned(pPrimSegments[1]) + unsigned(pPrimSegments[3])) / 2.0 + 0.5);
  40. if(u_segs == 0)
  41. {
  42. u_segs = 1;
  43. }
  44. if(v_segs == 0)
  45. {
  46. v_segs = 1;
  47. }
  48. if(unsigned(pPrimSegments[0]) != unsigned(pPrimSegments[2]) || unsigned(pPrimSegments[1]) != unsigned(pPrimSegments[3]))
  49. {
  50. // First, gulp, the irregular outside
  51. // To make life easier, we don't want to deal with the case when u_segs or v_segs is one
  52. // This ensures that there is at least one inside point
  53. if(u_segs == 1)
  54. {
  55. u_segs = 2;
  56. }
  57. if(v_segs == 1)
  58. {
  59. v_segs = 2;
  60. }
  61. // Start with top edge
  62. unsigned segs = unsigned(pPrimSegments[0]);
  63. unsigned k_outer = 0;
  64. unsigned k_inner = 1;
  65. unsigned outer_inc = u_segs - 2;
  66. unsigned inner_inc = segs;
  67. unsigned outer = 0;
  68. unsigned inner = 0;
  69. double u0, v0, u1, v1, u2, v2;
  70. while(outer_inc != 0 ? (inner != inner_inc * outer_inc || outer != inner_inc * outer_inc) : (k_outer < segs))
  71. {
  72. bool D0, D1, D2;
  73. if(inner < outer)
  74. {
  75. _ASSERT(k_inner < u_segs - 1, "Error in logic");
  76. u0 = double(k_inner) / double(u_segs);
  77. v0 = 1.0 / double(v_segs);
  78. D0 = false;
  79. u1 = double(k_outer) / double(segs);
  80. v1 = 0.0;
  81. D1 = bDegenerate;
  82. u2 = double(k_inner + 1) / double(u_segs);
  83. v2 = v0;
  84. D2 = false;
  85. ++k_inner;
  86. inner += inner_inc;
  87. }
  88. else
  89. {
  90. _ASSERT(k_outer < segs, "Error in logic");
  91. u0 = double(k_inner) / double(u_segs);
  92. v0 = 1.0 / double(v_segs);
  93. D0 = false;
  94. u1 = double(k_outer) / double(segs);
  95. v1 = 0.0;
  96. D1 = bDegenerate;
  97. u2 = double(k_outer + 1) / double(segs);
  98. v2 = v1;
  99. D2 = bDegenerate;
  100. ++k_outer;
  101. outer += outer_inc;
  102. }
  103. HRESULT hr = DrawTessTri(bz, dwOffW, dwOffH, dwStride, M, N, u0, v0, u1, v1, u2, v2,
  104. bDegenerate ? u0 * v0 : u0, v0, bDegenerate ? u1 * v1 : u1, v1, bDegenerate ? u2 * v2 : u2, v2,
  105. D0, D1, D2);
  106. if(FAILED(hr))
  107. {
  108. return hr;
  109. }
  110. }
  111. // bottom edge
  112. segs = unsigned(pPrimSegments[2]);
  113. k_outer = segs;
  114. k_inner = u_segs - 1;
  115. inner_inc = segs;
  116. outer = 0;
  117. inner = 0;
  118. while(outer_inc != 0 ? (inner != inner_inc * outer_inc || outer != inner_inc * outer_inc) : (k_outer > 0))
  119. {
  120. if(inner < outer)
  121. {
  122. _ASSERT(k_inner > 1, "Error in logic");
  123. u0 = double(k_inner) / double(u_segs);
  124. v0 = double(v_segs - 1) / double(v_segs);
  125. u1 = double(k_outer) / double(segs);
  126. v1 = 1.0;
  127. u2 = double(k_inner - 1) / double(u_segs);
  128. v2 = v0;
  129. --k_inner;
  130. inner += inner_inc;
  131. }
  132. else
  133. {
  134. _ASSERT(k_outer > 0, "Error in logic");
  135. u0 = double(k_inner) / double(u_segs);
  136. v0 = double(v_segs - 1) / double(v_segs);
  137. u1 = double(k_outer) / double(segs);
  138. v1 = 1.0;
  139. u2 = double(k_outer - 1) / double(segs);
  140. v2 = v1;
  141. --k_outer;
  142. outer += outer_inc;
  143. }
  144. HRESULT hr = DrawTessTri(bz, dwOffW, dwOffH, dwStride, M, N, u0, v0, u1, v1, u2, v2,
  145. bDegenerate ? u0 * v0 : u0, v0, bDegenerate ? u1 * v1 : u1, v1, bDegenerate ? u2 * v2 : u2, v2,
  146. false, false, false);
  147. if(FAILED(hr))
  148. {
  149. return hr;
  150. }
  151. }
  152. // right edge
  153. segs = unsigned(pPrimSegments[1]);
  154. k_outer = 0;
  155. k_inner = 1;
  156. outer_inc = v_segs - 2;
  157. inner_inc = segs;
  158. outer = 0;
  159. inner = 0;
  160. while(outer_inc != 0 ? (inner != inner_inc * outer_inc || outer != inner_inc * outer_inc) : (k_outer < segs))
  161. {
  162. bool D1;
  163. if(inner < outer)
  164. {
  165. _ASSERT(k_inner < v_segs - 1, "Error in logic");
  166. u0 = double(u_segs - 1) / double(u_segs);
  167. v0 = double(k_inner) / double(v_segs);
  168. u1 = 1.0;
  169. v1 = double(k_outer) / double(segs);
  170. D1 = (k_outer == 0) ? bDegenerate : false;
  171. u2 = u0;
  172. v2 = double(k_inner + 1) / double(v_segs);
  173. ++k_inner;
  174. inner += inner_inc;
  175. }
  176. else
  177. {
  178. _ASSERT(k_outer < segs, "Error in logic");
  179. u0 = double(u_segs - 1) / double(u_segs);
  180. v0 = double(k_inner) / double(v_segs);
  181. u1 = 1.0;
  182. v1 = double(k_outer) / double(segs);
  183. D1 = (k_outer == 0) ? bDegenerate : false;
  184. u2 = u1;
  185. v2 = double(k_outer + 1) / double(segs);
  186. ++k_outer;
  187. outer += outer_inc;
  188. }
  189. HRESULT hr = DrawTessTri(bz, dwOffW, dwOffH, dwStride, M, N, u0, v0, u1, v1, u2, v2,
  190. bDegenerate ? u0 * v0 : u0, v0, bDegenerate ? u1 * v1 : u1, v1, bDegenerate ? u2 * v2 : u2, v2,
  191. false, D1, false);
  192. if(FAILED(hr))
  193. {
  194. return hr;
  195. }
  196. }
  197. // left edge
  198. segs = unsigned(pPrimSegments[3]);
  199. k_outer = segs;
  200. k_inner = v_segs - 1;
  201. inner_inc = segs;
  202. outer = 0;
  203. inner = 0;
  204. while(outer_inc != 0 ? (inner != inner_inc * outer_inc || outer != inner_inc * outer_inc) : (k_outer > 0))
  205. {
  206. bool D1, D2;
  207. if(inner < outer)
  208. {
  209. _ASSERT(k_inner > 1, "Error in logic");
  210. u0 = 1.0 / double(u_segs);
  211. v0 = double(k_inner) / double(v_segs);
  212. u1 = 0.0;
  213. v1 = double(k_outer) / double(segs);
  214. D1 = (k_outer == 0) ? bDegenerate : false;
  215. u2 = u0;
  216. v2 = double(k_inner - 1) / double(v_segs);
  217. D2 = false;
  218. --k_inner;
  219. inner += inner_inc;
  220. }
  221. else
  222. {
  223. _ASSERT(k_outer > 0, "Error in logic");
  224. u0 = 1.0 / double(u_segs);
  225. v0 = double(k_inner) / double(v_segs);
  226. u1 = 0.0;
  227. v1 = double(k_outer) / double(segs);
  228. D1 = false; // since k_outer always > 0
  229. u2 = u1;
  230. v2 = double(k_outer - 1) / double(segs);
  231. D2 = (k_outer - 1 == 0) ? bDegenerate : false;
  232. --k_outer;
  233. outer += outer_inc;
  234. }
  235. HRESULT hr = DrawTessTri(bz, dwOffW, dwOffH, dwStride, M, N, u0, v0, u1, v1, u2, v2,
  236. bDegenerate ? u0 * v0 : u0, v0, bDegenerate ? u1 * v1 : u1, v1, bDegenerate ? u2 * v2 : u2, v2,
  237. false, D1, D2);
  238. if(FAILED(hr))
  239. {
  240. return hr;
  241. }
  242. }
  243. // Now do the regular interior
  244. u_start = 1;
  245. v_start = 1;
  246. }
  247. else
  248. {
  249. // It can be done regularly
  250. u_start = 0;
  251. v_start = 0;
  252. }
  253. }
  254. else
  255. {
  256. unsigned segs = unsigned(GetRSf()[D3DRS_PATCHSEGMENTS]);
  257. if(segs == 0)
  258. {
  259. segs = 1;
  260. }
  261. u_start = 0;
  262. v_start = 0;
  263. u_segs = segs;
  264. v_segs = segs;
  265. }
  266. for(unsigned i = v_start; i < v_segs - v_start; ++i)
  267. {
  268. double v0 = double(i) / double(v_segs);
  269. double v1 = double(i + 1) / double(v_segs);
  270. for(unsigned j = u_start; j < u_segs - u_start; ++j)
  271. {
  272. double u0 = double(j) / double(u_segs);
  273. double u1 = double(j + 1) / double(u_segs);
  274. if(i == 0 && bDegenerate)
  275. {
  276. HRESULT hr = DrawTessTri(bz, dwOffW, dwOffH, dwStride, M, N, u0, v0, u1, v1, u0, v1, u0 * v0, v0, u1 * v1, v1, u0 * v1, v1, true, false, false);
  277. if(FAILED(hr))
  278. {
  279. return hr;
  280. }
  281. }
  282. else
  283. {
  284. HRESULT hr = DrawTessQuad(bz, dwOffW, dwOffH, dwStride, M, N, u0, v0, u1, v1, u0, v0, u1, v1, bDegenerate);
  285. if(FAILED(hr))
  286. {
  287. return hr;
  288. }
  289. }
  290. }
  291. }
  292. return S_OK;
  293. }
  294. //-----------------------------------------------------------------------------
  295. // RDBezier::RDBezier
  296. //-----------------------------------------------------------------------------
  297. RDBezier::RDBezier(DWORD dwOrderU, DWORD dwOrderV)
  298. : RDBSpline(dwOrderU, dwOrderV, dwOrderU - 1, dwOrderV - 1)
  299. {
  300. for(unsigned n = 1; n <= 12; ++n)
  301. {
  302. for(unsigned i = 0; i <= n; ++i)
  303. {
  304. m_lut[n][i] = double(factorial(n)) / (double(factorial(i)) * double(factorial(n - i)));
  305. }
  306. }
  307. }
  308. //-----------------------------------------------------------------------------
  309. // RDBSpline::TexCoordU
  310. //-----------------------------------------------------------------------------
  311. double RDBezier::TexCoordU(double u) const
  312. {
  313. return u;
  314. }
  315. //-----------------------------------------------------------------------------
  316. // RDBSpline::TexCoordV
  317. //-----------------------------------------------------------------------------
  318. double RDBezier::TexCoordV(double v) const
  319. {
  320. return v;
  321. }
  322. //-----------------------------------------------------------------------------
  323. // RDBezier::Basis
  324. //-----------------------------------------------------------------------------
  325. double RDBezier::Basis(unsigned i, unsigned n, double t) const
  326. {
  327. _ASSERT(n < 13, "Order out of range");
  328. return m_lut[n][i] * pow(t, double(i)) * pow(1.0 - t, double(n - i));
  329. }
  330. //-----------------------------------------------------------------------------
  331. // RDBezier::BasisPrime
  332. //-----------------------------------------------------------------------------
  333. double RDBezier::BasisPrime(unsigned i, unsigned n, double t) const
  334. {
  335. _ASSERT(n < 13, "Order out of range");
  336. if(i == 0)
  337. {
  338. return m_lut[n][i] * -double(n) * pow(1 - t, n - 1);
  339. }
  340. else if(i == n)
  341. {
  342. return m_lut[n][i] * double(n) * pow(t, n - 1);
  343. }
  344. else
  345. {
  346. return (double(i) - double(n) * t) * (m_lut[n][i] * pow(t, double(i) - 1.0) * pow(1.0 - t, double(n - i) - 1.0));
  347. }
  348. }