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.

610 lines
24 KiB

  1. /*============================================================================
  2. *
  3. * Copyright (C) 1999-2000 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: bspline.cpp
  6. * Content: Implementation for B-Splines
  7. *
  8. ****************************************************************************/
  9. #include "pch.cpp"
  10. #pragma hdrstop
  11. //-----------------------------------------------------------------------------
  12. // RefDev::ProcessBSpline
  13. //-----------------------------------------------------------------------------
  14. HRESULT RefDev::ProcessBSpline( DWORD dwOffW, DWORD dwOffH,
  15. DWORD dwWidth, DWORD dwHeight,
  16. DWORD dwStride, DWORD order,
  17. FLOAT *pPrimSegments )
  18. {
  19. if(order == 0)
  20. {
  21. order = 2;
  22. }
  23. else
  24. {
  25. ++order;
  26. }
  27. int u_range = dwWidth - (order - 1);
  28. int v_range = dwHeight - (order - 1);
  29. if(u_range <= 0 || v_range <= 0)
  30. {
  31. DPFERR("Insufficient control vertices for current order");
  32. return DDERR_INVALIDPARAMS;
  33. }
  34. RDBSpline bsp(dwWidth, dwHeight, order, order);
  35. static const unsigned M[4] = {0, 0, 0, 0}, N[4] = {0, 0, 0, 0};
  36. unsigned u_segs, v_segs, u_start, v_start;
  37. if(pPrimSegments != 0)
  38. {
  39. u_segs = unsigned(double(unsigned(pPrimSegments[0]) + unsigned(pPrimSegments[2])) / 2.0 + 0.5);
  40. v_segs = unsigned(double(unsigned(pPrimSegments[1]) + unsigned(pPrimSegments[3])) / 2.0 + 0.5);
  41. if(u_segs == 0)
  42. {
  43. u_segs = 1;
  44. }
  45. if(v_segs == 0)
  46. {
  47. v_segs = 1;
  48. }
  49. if(unsigned(pPrimSegments[0]) != unsigned(pPrimSegments[2]) || unsigned(pPrimSegments[1]) != unsigned(pPrimSegments[3]))
  50. {
  51. // First, gulp, the irregular outside
  52. // To make life easier, we don't want to deal with the case when u_segs or v_segs is one
  53. // This ensures that there is at least one inside point
  54. if(u_segs == 1)
  55. {
  56. u_segs = 2;
  57. }
  58. if(v_segs == 1)
  59. {
  60. v_segs = 2;
  61. }
  62. // Start with top edge
  63. unsigned segs = unsigned(pPrimSegments[0]);
  64. unsigned k_outer = 0;
  65. unsigned k_inner = 1;
  66. unsigned outer_inc = u_segs - 2;
  67. unsigned inner_inc = segs;
  68. unsigned outer = 0;
  69. unsigned inner = 0;
  70. double u0, v0, u1, v1, u2, v2;
  71. while(outer_inc != 0 ? (inner != inner_inc * outer_inc || outer != inner_inc * outer_inc) : (k_outer < segs))
  72. {
  73. if(inner < outer)
  74. {
  75. _ASSERT(k_inner < u_segs - 1, "Error in logic");
  76. u0 = double(u_range * k_inner) / double(u_segs) + double(order - 1);
  77. v0 = double(v_range) / double(v_segs) + double(order - 1);
  78. u1 = double(u_range * k_outer) / double(segs) + double(order - 1);
  79. v1 = double(order - 1);
  80. u2 = double(u_range * (k_inner + 1)) / double(u_segs) + double(order - 1);
  81. v2 = v0;
  82. ++k_inner;
  83. inner += inner_inc;
  84. }
  85. else
  86. {
  87. _ASSERT(k_outer < segs, "Error in logic");
  88. u0 = double(u_range * k_inner) / double(u_segs) + double(order - 1);
  89. v0 = double(v_range) / double(v_segs) + double(order - 1);
  90. u1 = double(u_range * k_outer) / double(segs) + double(order - 1);
  91. v1 = double(order - 1);
  92. u2 = double(u_range * (k_outer + 1)) / double(segs) + double(order - 1);
  93. v2 = v1;
  94. ++k_outer;
  95. outer += outer_inc;
  96. }
  97. HRESULT hr = DrawTessTri(bsp, dwOffW, dwOffH, dwStride, M, N, u0, v0, u1, v1, u2, v2,
  98. bsp.TexCoordU(u0), bsp.TexCoordV(v0),
  99. bsp.TexCoordU(u1), bsp.TexCoordV(v1),
  100. bsp.TexCoordU(u2), bsp.TexCoordV(v2),
  101. false, false, false);
  102. if(FAILED(hr))
  103. {
  104. return hr;
  105. }
  106. }
  107. // bottom edge
  108. segs = unsigned(pPrimSegments[2]);
  109. k_outer = segs;
  110. k_inner = u_segs - 1;
  111. inner_inc = segs;
  112. outer = 0;
  113. inner = 0;
  114. while(outer_inc != 0 ? (inner != inner_inc * outer_inc || outer != inner_inc * outer_inc) : (k_outer > 0))
  115. {
  116. if(inner < outer)
  117. {
  118. _ASSERT(k_inner > 1, "Error in logic");
  119. u0 = double(u_range * k_inner) / double(u_segs) + double(order - 1);
  120. v0 = double(v_range * (v_segs - 1)) / double(v_segs) + double(order - 1);
  121. u1 = double(u_range * k_outer) / double(segs) + double(order - 1);
  122. v1 = double(v_range + order - 1);
  123. u2 = double(u_range * (k_inner - 1)) / double(u_segs) + double(order - 1);
  124. v2 = v0;
  125. --k_inner;
  126. inner += inner_inc;
  127. }
  128. else
  129. {
  130. _ASSERT(k_outer > 0, "Error in logic");
  131. u0 = double(u_range * k_inner) / double(u_segs) + double(order - 1);
  132. v0 = double(v_range * (v_segs - 1)) / double(v_segs) + double(order - 1);
  133. u1 = double(u_range * k_outer) / double(segs) + double(order - 1);
  134. v1 = double(v_range + order - 1);
  135. u2 = double(u_range * (k_outer - 1)) / double(segs) + double(order - 1);
  136. v2 = v1;
  137. --k_outer;
  138. outer += outer_inc;
  139. }
  140. HRESULT hr = DrawTessTri(bsp, dwOffW, dwOffH, dwStride, M, N, u0, v0, u1, v1, u2, v2,
  141. bsp.TexCoordU(u0), bsp.TexCoordV(v0),
  142. bsp.TexCoordU(u1), bsp.TexCoordV(v1),
  143. bsp.TexCoordU(u2), bsp.TexCoordV(v2),
  144. false, false, false);
  145. if(FAILED(hr))
  146. {
  147. return hr;
  148. }
  149. }
  150. // right edge
  151. segs = unsigned(pPrimSegments[1]);
  152. k_outer = 0;
  153. k_inner = 1;
  154. outer_inc = v_segs - 2;
  155. inner_inc = segs;
  156. outer = 0;
  157. inner = 0;
  158. while(outer_inc != 0 ? (inner != inner_inc * outer_inc || outer != inner_inc * outer_inc) : (k_outer < segs))
  159. {
  160. if(inner < outer)
  161. {
  162. _ASSERT(k_inner < v_segs - 1, "Error in logic");
  163. u0 = double(u_range * (u_segs - 1)) / double(u_segs) + double(order - 1);
  164. v0 = double(v_range * k_inner) / double(v_segs) + double(order - 1);
  165. u1 = double(u_range + order - 1);
  166. v1 = double(v_range * k_outer) / double(segs) + double(order - 1);
  167. u2 = u0;
  168. v2 = double(v_range * (k_inner + 1)) / double(v_segs) + double(order - 1);
  169. ++k_inner;
  170. inner += inner_inc;
  171. }
  172. else
  173. {
  174. _ASSERT(k_outer < segs, "Error in logic");
  175. u0 = double(u_range * (u_segs - 1)) / double(u_segs) + double(order - 1);
  176. v0 = double(v_range * k_inner) / double(v_segs) + double(order - 1);
  177. u1 = double(u_range + order - 1);
  178. v1 = double(v_range * k_outer) / double(segs) + double(order - 1);
  179. u2 = u1;
  180. v2 = double(v_range * (k_outer + 1)) / double(segs) + double(order - 1);
  181. ++k_outer;
  182. outer += outer_inc;
  183. }
  184. HRESULT hr = DrawTessTri(bsp, dwOffW, dwOffH, dwStride, M, N, u0, v0, u1, v1, u2, v2,
  185. bsp.TexCoordU(u0), bsp.TexCoordV(v0),
  186. bsp.TexCoordU(u1), bsp.TexCoordV(v1),
  187. bsp.TexCoordU(u2), bsp.TexCoordV(v2),
  188. false, false, false);
  189. if(FAILED(hr))
  190. {
  191. return hr;
  192. }
  193. }
  194. // left edge
  195. segs = unsigned(pPrimSegments[3]);
  196. k_outer = segs;
  197. k_inner = v_segs - 1;
  198. inner_inc = segs;
  199. outer = 0;
  200. inner = 0;
  201. while(outer_inc != 0 ? (inner != inner_inc * outer_inc || outer != inner_inc * outer_inc) : (k_outer > 0))
  202. {
  203. if(inner < outer)
  204. {
  205. _ASSERT(k_inner > 1, "Error in logic");
  206. u0 = double(u_range) / double(u_segs) + double(order - 1);
  207. v0 = double(v_range * k_inner) / double(v_segs) + double(order - 1);
  208. u1 = double(order - 1);
  209. v1 = double(v_range * k_outer) / double(segs) + double(order - 1);
  210. u2 = u0;
  211. v2 = double(v_range * (k_inner - 1)) / double(v_segs) + double(order - 1);
  212. --k_inner;
  213. inner += inner_inc;
  214. }
  215. else
  216. {
  217. _ASSERT(k_outer > 0, "Error in logic");
  218. u0 = double(u_range) / double(u_segs) + double(order - 1);
  219. v0 = double(v_range * k_inner) / double(v_segs) + double(order - 1);
  220. u1 = double(order - 1);
  221. v1 = double(v_range * k_outer) / double(segs) + double(order - 1);
  222. u2 = u1;
  223. v2 = double(v_range * (k_outer - 1)) / double(segs) + double(order - 1);
  224. --k_outer;
  225. outer += outer_inc;
  226. }
  227. HRESULT hr = DrawTessTri(bsp, dwOffW, dwOffH, dwStride, M, N, u0, v0, u1, v1, u2, v2,
  228. bsp.TexCoordU(u0), bsp.TexCoordV(v0),
  229. bsp.TexCoordU(u1), bsp.TexCoordV(v1),
  230. bsp.TexCoordU(u2), bsp.TexCoordV(v2),
  231. false, false, false);
  232. if(FAILED(hr))
  233. {
  234. return hr;
  235. }
  236. }
  237. // Now do the regular interior
  238. u_start = 1;
  239. v_start = 1;
  240. }
  241. else
  242. {
  243. // It can be done regularly
  244. u_start = 0;
  245. v_start = 0;
  246. }
  247. }
  248. else
  249. {
  250. unsigned segs = unsigned(GetRSf()[D3DRS_PATCHSEGMENTS]);
  251. if(segs == 0)
  252. {
  253. segs = 1;
  254. }
  255. u_start = 0;
  256. v_start = 0;
  257. u_segs = segs;
  258. v_segs = segs;
  259. }
  260. for(unsigned i = v_start; i < v_segs - v_start; ++i)
  261. {
  262. double v0 = double(v_range * i) / double(v_segs) + double(order - 1);
  263. double v1 = double(v_range * (i + 1)) / double(v_segs) + double(order - 1);
  264. for(unsigned j = u_start; j < u_segs - u_start; ++j)
  265. {
  266. double u0 = double(u_range * j) / double(u_segs) + double(order - 1);
  267. double u1 = double(u_range * (j + 1)) / double(u_segs) + double(order - 1);
  268. HRESULT hr = DrawTessQuad(bsp, dwOffW, dwOffH, dwStride, M, N, u0, v0, u1, v1,
  269. bsp.TexCoordU(u0), bsp.TexCoordV(v0),
  270. bsp.TexCoordU(u1), bsp.TexCoordV(v1),
  271. false);
  272. if(FAILED(hr))
  273. {
  274. return hr;
  275. }
  276. }
  277. }
  278. return S_OK;
  279. }
  280. //-----------------------------------------------------------------------------
  281. // RDBSpline::Sample
  282. //-----------------------------------------------------------------------------
  283. void RDBSpline::Sample(DWORD dwDataType, double u, double v, const BYTE *pRow, DWORD dwStride, DWORD dwPitch, BYTE *Q) const
  284. {
  285. double Acc[4] = {0.0, 0.0, 0.0, 0.0};
  286. unsigned dwElements = 0;
  287. switch(dwDataType)
  288. {
  289. case D3DVSDT_FLOAT4:
  290. ++dwElements;
  291. case D3DVSDT_FLOAT3:
  292. ++dwElements;
  293. case D3DVSDT_FLOAT2:
  294. ++dwElements;
  295. case D3DVSDT_FLOAT1:
  296. ++dwElements;
  297. {
  298. for(unsigned i = 0; i < m_dwHeight; ++i)
  299. {
  300. double N = Basis(i, m_dwOrderV, v);
  301. const BYTE *pCol = pRow;
  302. for(unsigned j = 0; j < m_dwWidth; ++j)
  303. {
  304. double NM = N * Basis(j, m_dwOrderU, u);
  305. const FLOAT *B = (FLOAT*)pCol;
  306. for(unsigned e = 0; e < dwElements; ++e)
  307. {
  308. Acc[e] += double(B[e]) * NM;
  309. }
  310. pCol += dwStride;
  311. }
  312. pRow += dwPitch;
  313. }
  314. for(unsigned e = 0; e < dwElements; ++e)
  315. {
  316. ((FLOAT*)Q)[e] = FLOAT(Acc[e]);
  317. }
  318. }
  319. break;
  320. case D3DVSDT_D3DCOLOR:
  321. case D3DVSDT_UBYTE4:
  322. dwElements = 4;
  323. {
  324. for(unsigned i = 0; i < m_dwHeight; ++i)
  325. {
  326. double N = Basis(i, m_dwOrderV, v);
  327. const BYTE *pCol = pRow;
  328. for(unsigned j = 0; j < m_dwWidth; ++j)
  329. {
  330. double NM = N * Basis(j, m_dwOrderU, u);
  331. const BYTE *B = pCol;
  332. for(unsigned e = 0; e < 4; ++e)
  333. {
  334. Acc[e] += double(B[e]) * NM;
  335. }
  336. pCol += dwStride;
  337. }
  338. pRow += dwPitch;
  339. }
  340. for(unsigned e = 0; e < 4; ++e)
  341. {
  342. int t = int(Acc[e]);
  343. Q[e] = BYTE(t < 0 ? 0 : (t > 255 ? 255 : t));
  344. }
  345. }
  346. break;
  347. case D3DVSDT_SHORT4:
  348. dwElements += 2;
  349. case D3DVSDT_SHORT2:
  350. dwElements += 2;
  351. {
  352. for(unsigned i = 0; i < m_dwHeight; ++i)
  353. {
  354. double N = Basis(i, m_dwOrderV, v);
  355. const BYTE *pCol = pRow;
  356. for(unsigned j = 0; j < m_dwWidth; ++j)
  357. {
  358. double NM = N * Basis(j, m_dwOrderU, u);
  359. const SHORT *B = (SHORT*)pCol;
  360. for(unsigned e = 0; e < dwElements; ++e)
  361. {
  362. Acc[e] += double(B[e]) * NM;
  363. }
  364. pCol += dwStride;
  365. }
  366. pRow += dwPitch;
  367. }
  368. for(unsigned e = 0; e < dwElements; ++e)
  369. {
  370. ((SHORT*)Q)[e] = SHORT(Acc[e]);
  371. }
  372. }
  373. break;
  374. default:
  375. _ASSERT(FALSE, "Ununderstood vertex element data type");
  376. }
  377. }
  378. //-----------------------------------------------------------------------------
  379. // RDBSpline::SampleNormal
  380. //-----------------------------------------------------------------------------
  381. void RDBSpline::SampleNormal(DWORD dwDataType, double u, double v, const BYTE *pRow, DWORD dwStride, DWORD dwPitch, BYTE *Q) const
  382. {
  383. double Acc[2][3] = {{0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}};
  384. // Fudge u and v if they are on the boundary. This is because the derivative is discontinuous on the boundary
  385. // and we really want it to be slightly inside the boundary.
  386. if(v == double(m_dwHeight))
  387. {
  388. v -= v * DBL_EPSILON;
  389. }
  390. if(u == double(m_dwWidth))
  391. {
  392. u -= u * DBL_EPSILON;
  393. }
  394. switch(dwDataType)
  395. {
  396. case D3DVSDT_FLOAT4:
  397. case D3DVSDT_FLOAT3:
  398. {
  399. for(unsigned i = 0; i < m_dwHeight; ++i)
  400. {
  401. double N = Basis(i, m_dwOrderV, v);
  402. double NPrime = BasisPrime(i, m_dwOrderV, v);
  403. const BYTE *pCol = pRow;
  404. for(unsigned j = 0; j < m_dwWidth; ++j)
  405. {
  406. double NMPrime = N * BasisPrime(j, m_dwOrderU, u);
  407. double NPrimeM = NPrime * Basis(j, m_dwOrderU, u);
  408. const FLOAT *B = (FLOAT*)pCol;
  409. for(unsigned e = 0; e < 3; ++e)
  410. {
  411. Acc[0][e] += double(B[e]) * NMPrime;
  412. Acc[1][e] += double(B[e]) * NPrimeM;
  413. }
  414. pCol += dwStride;
  415. }
  416. pRow += dwPitch;
  417. }
  418. ((FLOAT*)Q)[0] = FLOAT(Acc[0][1] * Acc[1][2] - Acc[0][2] * Acc[1][1]);
  419. ((FLOAT*)Q)[1] = FLOAT(Acc[0][2] * Acc[1][0] - Acc[0][0] * Acc[1][2]);
  420. ((FLOAT*)Q)[2] = FLOAT(Acc[0][0] * Acc[1][1] - Acc[0][1] * Acc[1][0]);
  421. }
  422. break;
  423. case D3DVSDT_D3DCOLOR:
  424. case D3DVSDT_UBYTE4:
  425. {
  426. for(unsigned i = 0; i < m_dwHeight; ++i)
  427. {
  428. double N = Basis(i, m_dwOrderV, v);
  429. double NPrime = BasisPrime(i, m_dwOrderV, v);
  430. const BYTE *pCol = pRow;
  431. for(unsigned j = 0; j < m_dwWidth; ++j)
  432. {
  433. double NMPrime = N * BasisPrime(j, m_dwOrderU, u);
  434. double NPrimeM = NPrime * Basis(j, m_dwOrderU, u);
  435. const BYTE *B = pCol;
  436. for(unsigned e = 0; e < 3; ++e)
  437. {
  438. Acc[0][e] += double(B[e]) * NMPrime;
  439. Acc[1][e] += double(B[e]) * NPrimeM;
  440. }
  441. pCol += dwStride;
  442. }
  443. pRow += dwPitch;
  444. }
  445. ((FLOAT*)Q)[0] = FLOAT(Acc[0][1] * Acc[1][2] - Acc[0][2] * Acc[1][1]);
  446. ((FLOAT*)Q)[1] = FLOAT(Acc[0][2] * Acc[1][0] - Acc[0][0] * Acc[1][2]);
  447. ((FLOAT*)Q)[2] = FLOAT(Acc[0][0] * Acc[1][1] - Acc[0][1] * Acc[1][0]);
  448. }
  449. break;
  450. case D3DVSDT_SHORT4:
  451. {
  452. for(unsigned i = 0; i < m_dwHeight; ++i)
  453. {
  454. double N = Basis(i, m_dwOrderV, v);
  455. double NPrime = BasisPrime(i, m_dwOrderV, v);
  456. const BYTE *pCol = pRow;
  457. for(unsigned j = 0; j < m_dwWidth; ++j)
  458. {
  459. double NMPrime = N * BasisPrime(j, m_dwOrderU, u);
  460. double NPrimeM = NPrime * Basis(j, m_dwOrderU, u);
  461. const SHORT *B = (SHORT*)pCol;
  462. for(unsigned e = 0; e < 3; ++e)
  463. {
  464. Acc[0][e] += double(B[e]) * NMPrime;
  465. Acc[1][e] += double(B[e]) * NPrimeM;
  466. }
  467. pCol += dwStride;
  468. }
  469. pRow += dwPitch;
  470. }
  471. ((FLOAT*)Q)[0] = FLOAT(Acc[0][1] * Acc[1][2] - Acc[0][2] * Acc[1][1]);
  472. ((FLOAT*)Q)[1] = FLOAT(Acc[0][2] * Acc[1][0] - Acc[0][0] * Acc[1][2]);
  473. ((FLOAT*)Q)[2] = FLOAT(Acc[0][0] * Acc[1][1] - Acc[0][1] * Acc[1][0]);
  474. }
  475. break;
  476. case D3DVSDT_SHORT2:
  477. case D3DVSDT_FLOAT2:
  478. case D3DVSDT_FLOAT1:
  479. default:
  480. _ASSERT(FALSE, "Ununderstood vertex element data type");
  481. }
  482. }
  483. //-----------------------------------------------------------------------------
  484. // RDBSpline::SampleDegenerateNormal
  485. //-----------------------------------------------------------------------------
  486. void RDBSpline::SampleDegenerateNormal(DWORD dwDataType, const BYTE *pRow, DWORD dwStride, DWORD dwPitch, BYTE *Q) const
  487. {
  488. double Acc[2][3] = {{0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}};
  489. switch(dwDataType)
  490. {
  491. case D3DVSDT_FLOAT4:
  492. case D3DVSDT_FLOAT3:
  493. {
  494. for(unsigned i = 0; i < m_dwHeight; ++i)
  495. {
  496. double JPrime = BasisPrime(i, m_dwOrderV, 0.0);
  497. const FLOAT *B1 = (FLOAT*)pRow;
  498. const FLOAT *B2 = (FLOAT*)(pRow + (m_dwWidth - 1) * dwStride);
  499. for(unsigned e = 0; e < 3; ++e)
  500. {
  501. Acc[0][e] += double(B2[e]) * JPrime;
  502. Acc[1][e] += double(B1[e]) * JPrime;
  503. }
  504. pRow += dwPitch;
  505. }
  506. ((FLOAT*)Q)[0] = FLOAT(Acc[0][1] * Acc[1][2] - Acc[0][2] * Acc[1][1]);
  507. ((FLOAT*)Q)[1] = FLOAT(Acc[0][2] * Acc[1][0] - Acc[0][0] * Acc[1][2]);
  508. ((FLOAT*)Q)[2] = FLOAT(Acc[0][0] * Acc[1][1] - Acc[0][1] * Acc[1][0]);
  509. }
  510. break;
  511. case D3DVSDT_D3DCOLOR:
  512. case D3DVSDT_UBYTE4:
  513. {
  514. for(unsigned i = 0; i < m_dwHeight; ++i)
  515. {
  516. double JPrime = BasisPrime(i, m_dwOrderV, 0.0);
  517. const BYTE *B1 = pRow;
  518. const BYTE *B2 = pRow + (m_dwWidth - 1) * dwStride;
  519. for(unsigned e = 0; e < 3; ++e)
  520. {
  521. Acc[0][e] += double(B2[e]) * JPrime;
  522. Acc[1][e] += double(B1[e]) * JPrime;
  523. }
  524. pRow += dwPitch;
  525. }
  526. ((FLOAT*)Q)[0] = FLOAT(Acc[0][1] * Acc[1][2] - Acc[0][2] * Acc[1][1]);
  527. ((FLOAT*)Q)[1] = FLOAT(Acc[0][2] * Acc[1][0] - Acc[0][0] * Acc[1][2]);
  528. ((FLOAT*)Q)[2] = FLOAT(Acc[0][0] * Acc[1][1] - Acc[0][1] * Acc[1][0]);
  529. }
  530. break;
  531. case D3DVSDT_SHORT4:
  532. {
  533. for(unsigned i = 0; i < m_dwHeight; ++i)
  534. {
  535. double JPrime = BasisPrime(i, m_dwOrderV, 0.0);
  536. const SHORT *B1 = (SHORT*)pRow;
  537. const SHORT *B2 = (SHORT*)(pRow + (m_dwWidth - 1) * dwStride);
  538. for(unsigned e = 0; e < 3; ++e)
  539. {
  540. Acc[0][e] += double(B2[e]) * JPrime;
  541. Acc[1][e] += double(B1[e]) * JPrime;
  542. }
  543. pRow += dwPitch;
  544. }
  545. ((FLOAT*)Q)[0] = FLOAT(Acc[0][1] * Acc[1][2] - Acc[0][2] * Acc[1][1]);
  546. ((FLOAT*)Q)[1] = FLOAT(Acc[0][2] * Acc[1][0] - Acc[0][0] * Acc[1][2]);
  547. ((FLOAT*)Q)[2] = FLOAT(Acc[0][0] * Acc[1][1] - Acc[0][1] * Acc[1][0]);
  548. }
  549. break;
  550. case D3DVSDT_FLOAT2:
  551. case D3DVSDT_FLOAT1:
  552. case D3DVSDT_SHORT2:
  553. default:
  554. _ASSERT(FALSE, "Ununderstood vertex element data type");
  555. }
  556. }
  557. //-----------------------------------------------------------------------------
  558. // RDBSpline::Basis
  559. //-----------------------------------------------------------------------------
  560. double RDBSpline::Basis(unsigned i, unsigned k, double s) const
  561. {
  562. if(k == 1)
  563. {
  564. if(Knot(i) <= s && s < Knot(i + 1))
  565. {
  566. return 1.0;
  567. }
  568. else
  569. {
  570. return 0.0;
  571. }
  572. }
  573. else
  574. {
  575. _ASSERT(k != 0, "Arithmatic error in RDBSpline::Basis");
  576. return ((s - Knot(i)) * Basis(i, k - 1, s)) / (Knot(i + k - 1) - Knot(i)) +
  577. ((Knot(i + k) - s) * Basis(i + 1, k - 1, s)) / (Knot(i + k) - Knot(i + 1));
  578. }
  579. }
  580. //-----------------------------------------------------------------------------
  581. // RDBSpline::BasisPrime
  582. //-----------------------------------------------------------------------------
  583. double RDBSpline::BasisPrime(unsigned i, unsigned k, double s) const
  584. {
  585. if(k == 1)
  586. {
  587. return 0.0;
  588. }
  589. else
  590. {
  591. _ASSERT(k != 0, "Arithmatic error in RDBSpline::BasisPrime");
  592. return (Basis(i, k - 1, s) + (s - Knot(i)) * BasisPrime(i, k - 1, s)) / (Knot(i + k - 1) - Knot(i)) +
  593. ((Knot(i + k) - s) * BasisPrime(i + 1, k - 1, s) - Basis(i + 1, k - 1, s)) / (Knot(i + k) - Knot(i + 1));
  594. }
  595. }