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.

546 lines
21 KiB

  1. /*============================================================================
  2. *
  3. * Copyright (C) 1999-2000 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: npatch.cpp
  6. * Content: Implementation for N-Patches
  7. *
  8. ****************************************************************************/
  9. #include "pch.cpp"
  10. #pragma hdrstop
  11. //-----------------------------------------------------------------------------
  12. // RefDev::ProcessTessPrimitive
  13. //-----------------------------------------------------------------------------
  14. HRESULT
  15. RefDev::ProcessTessPrimitive( LPD3DHAL_DP2DRAWPRIMITIVE pDP )
  16. {
  17. HRESULT hr = S_OK;
  18. if( RDVSD_ISLEGACY( m_CurrentVShaderHandle ) )
  19. {
  20. //
  21. // The legacy FVF style: The Zero'th Stream is implied
  22. //
  23. DWORD dwFVF = m_CurrentVShaderHandle;
  24. RDVStream& Stream = m_VStream[0];
  25. DWORD dwStride = Stream.m_dwStride;
  26. DWORD dwFVFSize = GetFVFVertexSize( dwFVF );
  27. if( Stream.m_pData == NULL || dwStride == 0 )
  28. {
  29. DPFERR( "Zero'th stream doesnt have valid VB set" );
  30. return DDERR_INVALIDPARAMS;
  31. }
  32. if( dwStride < dwFVFSize )
  33. {
  34. DPFERR( "The stride set for the vertex stream is less than"
  35. " the FVF vertex size" );
  36. return E_FAIL;
  37. }
  38. }
  39. BYTE *pVerts = 0, *pNorms = 0;
  40. unsigned vstride, nstride;
  41. // Figure out where the positions and normals are
  42. RDVDeclaration &Decl = m_pCurrentVShader->m_Declaration;
  43. for(unsigned e = 0; e < Decl.m_dwNumElements; ++e)
  44. {
  45. RDVElement &velem = Decl.m_VertexElements[e];
  46. if(velem.m_dwRegister == D3DVSDE_POSITION) // Position
  47. {
  48. RDVStream &vstream = m_VStream[velem.m_dwStreamIndex];
  49. pVerts = vstream.m_pSavedData + pDP->VStart * vstream.m_dwStride + velem.m_dwOffset;
  50. vstride = vstream.m_dwStride;
  51. }
  52. else if(velem.m_dwRegister == D3DVSDE_NORMAL) // Normal
  53. {
  54. RDVStream &vstream = m_VStream[velem.m_dwStreamIndex];
  55. pNorms = vstream.m_pSavedData + pDP->VStart * vstream.m_dwStride + velem.m_dwOffset;
  56. nstride = vstream.m_dwStride;
  57. }
  58. }
  59. if(pVerts == 0 || pNorms == 0)
  60. {
  61. DPFERR("This tessellation scheme needs positions and normals explicitely specified");
  62. return DDERR_INVALIDPARAMS;
  63. }
  64. switch(pDP->primType)
  65. {
  66. case D3DPT_TRIANGLELIST:
  67. {
  68. for(unsigned i = 0; i < pDP->PrimitiveCount; ++i)
  69. {
  70. FLOAT *pV[3], *pN[3];
  71. unsigned iM[3], iN[3];
  72. pV[0] = (FLOAT*)(pVerts + i * 3 * vstride);
  73. pV[1] = (FLOAT*)(pVerts + (i * 3 + 1) * vstride);
  74. pV[2] = (FLOAT*)(pVerts + (i * 3 + 2) * vstride);
  75. pN[0] = (FLOAT*)(pNorms + i * 3 * nstride);
  76. pN[1] = (FLOAT*)(pNorms + (i * 3 + 1) * nstride);
  77. pN[2] = (FLOAT*)(pNorms + (i * 3 + 2) * nstride);
  78. iM[0] = pDP->VStart + i * 3; iN[0] = 0;
  79. iM[1] = pDP->VStart + i * 3 + 1; iN[1] = 0;
  80. iM[2] = pDP->VStart + i * 3 + 2; iN[2] = 0;
  81. RDNPatch patch(pV, pN, GetRS()[D3DRS_POSITIONORDER], GetRS()[D3DRS_NORMALORDER]);
  82. hr = DrawNPatch(patch, 0, iM, iN, unsigned(GetRSf()[D3DRS_PATCHSEGMENTS]));
  83. if(FAILED(hr))
  84. {
  85. return hr;
  86. }
  87. }
  88. }
  89. break;
  90. case D3DPT_TRIANGLEFAN:
  91. {
  92. for(unsigned i = 0; i < pDP->PrimitiveCount; ++i)
  93. {
  94. FLOAT *pV[3], *pN[3];
  95. unsigned iM[3], iN[3];
  96. pV[0] = (FLOAT*)(pVerts);
  97. pV[1] = (FLOAT*)(pVerts + (i + 1) * vstride);
  98. pV[2] = (FLOAT*)(pVerts + (i + 2) * vstride);
  99. pN[0] = (FLOAT*)(pNorms);
  100. pN[1] = (FLOAT*)(pNorms + (i + 1) * nstride);
  101. pN[2] = (FLOAT*)(pNorms + (i + 2) * nstride);
  102. iM[0] = pDP->VStart; iN[0] = 0;
  103. iM[1] = pDP->VStart + i + 1; iN[1] = 0;
  104. iM[2] = pDP->VStart + i + 2; iN[2] = 0;
  105. RDNPatch patch(pV, pN, GetRS()[D3DRS_POSITIONORDER], GetRS()[D3DRS_NORMALORDER]);
  106. hr = DrawNPatch(patch, 0, iM, iN, unsigned(GetRSf()[D3DRS_PATCHSEGMENTS]));
  107. if(FAILED(hr))
  108. {
  109. return hr;
  110. }
  111. }
  112. }
  113. break;
  114. case D3DPT_TRIANGLESTRIP:
  115. {
  116. for(unsigned i = 0; i < pDP->PrimitiveCount; ++i)
  117. {
  118. FLOAT *pV[3], *pN[3];
  119. unsigned iM[3], iN[3];
  120. pV[0] = (FLOAT*)(pVerts + i * vstride);
  121. pN[0] = (FLOAT*)(pNorms + i * nstride);
  122. iM[0] = pDP->VStart + i; iN[0] = 0;
  123. iM[0] = pDP->VStart + i; iN[0] = 0;
  124. if((i & 1) != 0)
  125. {
  126. pV[1] = (FLOAT*)(pVerts + (i + 2) * vstride);
  127. pV[2] = (FLOAT*)(pVerts + (i + 1) * vstride);
  128. pN[1] = (FLOAT*)(pNorms + (i + 2) * nstride);
  129. pN[2] = (FLOAT*)(pNorms + (i + 1) * nstride);
  130. iM[1] = pDP->VStart + i + 2; iN[1] = 0;
  131. iM[2] = pDP->VStart + i + 1; iN[2] = 0;
  132. }
  133. else
  134. {
  135. pV[1] = (FLOAT*)(pVerts + (i + 1) * vstride);
  136. pV[2] = (FLOAT*)(pVerts + (i + 2) * vstride);
  137. pN[1] = (FLOAT*)(pNorms + (i + 1) * nstride);
  138. pN[2] = (FLOAT*)(pNorms + (i + 2) * nstride);
  139. iM[1] = pDP->VStart + i + 1; iN[1] = 0;
  140. iM[2] = pDP->VStart + i + 2; iN[2] = 0;
  141. }
  142. RDNPatch patch(pV, pN, GetRS()[D3DRS_POSITIONORDER], GetRS()[D3DRS_NORMALORDER]);
  143. hr = DrawNPatch(patch, 0, iM, iN, unsigned(GetRSf()[D3DRS_PATCHSEGMENTS]));
  144. if(FAILED(hr))
  145. {
  146. return hr;
  147. }
  148. }
  149. }
  150. break;
  151. default:
  152. _ASSERT(FALSE, "Unsupported primitive type");
  153. hr = E_FAIL;
  154. }
  155. return hr;
  156. }
  157. //-----------------------------------------------------------------------------
  158. // RefDev::ProcessTessIndexedPrimitive
  159. //-----------------------------------------------------------------------------
  160. HRESULT
  161. RefDev::ProcessTessIndexedPrimitive( LPD3DHAL_DP2DRAWINDEXEDPRIMITIVE pDIP )
  162. {
  163. HRESULT hr = S_OK;
  164. if( RDVSD_ISLEGACY( m_CurrentVShaderHandle ) )
  165. {
  166. //
  167. // The legacy FVF style: The Zero'th Stream is implied
  168. //
  169. DWORD dwFVF = m_CurrentVShaderHandle;
  170. RDVStream& Stream = m_VStream[0];
  171. DWORD dwStride = Stream.m_dwStride;
  172. DWORD dwFVFSize = GetFVFVertexSize( dwFVF );
  173. if( Stream.m_pData == NULL || dwStride == 0 )
  174. {
  175. DPFERR( "Zero'th stream doesnt have valid VB set" );
  176. return DDERR_INVALIDPARAMS;
  177. }
  178. if( dwStride < dwFVFSize )
  179. {
  180. DPFERR( "The stride set for the vertex stream is less than"
  181. " the FVF vertex size" );
  182. return E_FAIL;
  183. }
  184. if( m_IndexStream.m_pData == NULL )
  185. {
  186. DPFERR( "Indices are not available" );
  187. return E_FAIL;
  188. }
  189. }
  190. BYTE *pVerts = 0, *pNorms = 0;
  191. unsigned vstride, nstride;
  192. // Figure out where the positions and normals are
  193. RDVDeclaration &Decl = m_pCurrentVShader->m_Declaration;
  194. for(unsigned e = 0; e < Decl.m_dwNumElements; ++e)
  195. {
  196. RDVElement &velem = Decl.m_VertexElements[e];
  197. if(velem.m_dwRegister == D3DVSDE_POSITION) // Position
  198. {
  199. RDVStream &vstream = m_VStream[velem.m_dwStreamIndex];
  200. pVerts = vstream.m_pSavedData + pDIP->BaseVertexIndex * vstream.m_dwStride + velem.m_dwOffset;
  201. vstride = vstream.m_dwStride;
  202. }
  203. else if(velem.m_dwRegister == D3DVSDE_NORMAL) // Normal
  204. {
  205. RDVStream &vstream = m_VStream[velem.m_dwStreamIndex];
  206. pNorms = vstream.m_pSavedData + pDIP->BaseVertexIndex * vstream.m_dwStride + velem.m_dwOffset;
  207. nstride = vstream.m_dwStride;
  208. }
  209. }
  210. if(pVerts == 0 || pNorms == 0)
  211. {
  212. DPFERR("This tessellation scheme needs positions and normals explicitely specified");
  213. return DDERR_INVALIDPARAMS;
  214. }
  215. RRIndexAccessor Index(m_IndexStream.m_pData, m_IndexStream.m_dwStride, pDIP->StartIndex);
  216. switch(pDIP->primType)
  217. {
  218. case D3DPT_TRIANGLELIST:
  219. {
  220. for(unsigned i = 0; i < pDIP->PrimitiveCount; ++i)
  221. {
  222. FLOAT *pV[3], *pN[3];
  223. unsigned iM[3], iN[3];
  224. pV[0] = (FLOAT*)(pVerts + Index[i * 3] * vstride);
  225. pV[1] = (FLOAT*)(pVerts + Index[i * 3 + 1] * vstride);
  226. pV[2] = (FLOAT*)(pVerts + Index[i * 3 + 2] * vstride);
  227. pN[0] = (FLOAT*)(pNorms + Index[i * 3] * nstride);
  228. pN[1] = (FLOAT*)(pNorms + Index[i * 3 + 1] * nstride);
  229. pN[2] = (FLOAT*)(pNorms + Index[i * 3 + 2] * nstride);
  230. iM[0] = pDIP->BaseVertexIndex + Index[i * 3]; iN[0] = 0;
  231. iM[1] = pDIP->BaseVertexIndex + Index[i * 3 + 1]; iN[1] = 0;
  232. iM[2] = pDIP->BaseVertexIndex + Index[i * 3 + 2]; iN[2] = 0;
  233. RDNPatch patch(pV, pN, GetRS()[D3DRS_POSITIONORDER], GetRS()[D3DRS_NORMALORDER]);
  234. hr = DrawNPatch(patch, 0, iM, iN, unsigned(GetRSf()[D3DRS_PATCHSEGMENTS]));
  235. if(FAILED(hr))
  236. {
  237. return hr;
  238. }
  239. }
  240. }
  241. break;
  242. case D3DPT_TRIANGLEFAN:
  243. {
  244. for(unsigned i = 0; i < pDIP->PrimitiveCount; ++i)
  245. {
  246. FLOAT *pV[3], *pN[3];
  247. unsigned iM[3], iN[3];
  248. pV[0] = (FLOAT*)(pVerts + Index[0] * vstride);
  249. pV[1] = (FLOAT*)(pVerts + Index[i + 1] * vstride);
  250. pV[2] = (FLOAT*)(pVerts + Index[i + 2] * vstride);
  251. pN[0] = (FLOAT*)(pNorms + Index[0] * nstride);
  252. pN[1] = (FLOAT*)(pNorms + Index[i + 1] * nstride);
  253. pN[2] = (FLOAT*)(pNorms + Index[i + 2] * nstride);
  254. iM[0] = pDIP->BaseVertexIndex + Index[0]; iN[0] = 0;
  255. iM[1] = pDIP->BaseVertexIndex + Index[i + 1]; iN[1] = 0;
  256. iM[2] = pDIP->BaseVertexIndex + Index[i + 2]; iN[2] = 0;
  257. RDNPatch patch(pV, pN, GetRS()[D3DRS_POSITIONORDER], GetRS()[D3DRS_NORMALORDER]);
  258. hr = DrawNPatch(patch, 0, iM, iN, unsigned(GetRSf()[D3DRS_PATCHSEGMENTS]));
  259. if(FAILED(hr))
  260. {
  261. return hr;
  262. }
  263. }
  264. }
  265. break;
  266. case D3DPT_TRIANGLESTRIP:
  267. {
  268. for(unsigned i = 0; i < pDIP->PrimitiveCount; ++i)
  269. {
  270. FLOAT *pV[3], *pN[3];
  271. unsigned iM[3], iN[3];
  272. pV[0] = (FLOAT*)(pVerts + Index[i] * vstride);
  273. pN[0] = (FLOAT*)(pNorms + Index[i] * nstride);
  274. iM[0] = pDIP->BaseVertexIndex + Index[i]; iN[0] = 0;
  275. iM[0] = pDIP->BaseVertexIndex + Index[i]; iN[0] = 0;
  276. if((i & 1) != 0)
  277. {
  278. pV[1] = (FLOAT*)(pVerts + Index[i + 2] * vstride);
  279. pV[2] = (FLOAT*)(pVerts + Index[i + 1] * vstride);
  280. pN[1] = (FLOAT*)(pNorms + Index[i + 2] * nstride);
  281. pN[2] = (FLOAT*)(pNorms + Index[i + 1] * nstride);
  282. iM[1] = pDIP->BaseVertexIndex + Index[i + 2]; iN[1] = 0;
  283. iM[2] = pDIP->BaseVertexIndex + Index[i + 1]; iN[2] = 0;
  284. }
  285. else
  286. {
  287. pV[1] = (FLOAT*)(pVerts + Index[i + 1] * vstride);
  288. pV[2] = (FLOAT*)(pVerts + Index[i + 2] * vstride);
  289. pN[1] = (FLOAT*)(pNorms + Index[i + 1] * nstride);
  290. pN[2] = (FLOAT*)(pNorms + Index[i + 2] * nstride);
  291. iM[1] = pDIP->BaseVertexIndex + Index[i + 1]; iN[1] = 0;
  292. iM[2] = pDIP->BaseVertexIndex + Index[i + 2]; iN[2] = 0;
  293. }
  294. RDNPatch patch(pV, pN, GetRS()[D3DRS_POSITIONORDER], GetRS()[D3DRS_NORMALORDER]);
  295. hr = DrawNPatch(patch, 0, iM, iN, unsigned(GetRSf()[D3DRS_PATCHSEGMENTS]));
  296. if(FAILED(hr))
  297. {
  298. return hr;
  299. }
  300. }
  301. }
  302. break;
  303. default:
  304. _ASSERT(FALSE, "Unsupported primitive type");
  305. hr = E_FAIL;
  306. }
  307. return hr;
  308. }
  309. //-----------------------------------------------------------------------------
  310. // RDCubicBezierTriangle::SamplePosition
  311. //-----------------------------------------------------------------------------
  312. void RDCubicBezierTriangle::SamplePosition(double u, double v, FLOAT *Q) const
  313. {
  314. for(unsigned e = 0; e < 3; ++e)
  315. {
  316. Q[e] = FLOAT(m_B[0][0][e] * Basis(0, 0, u, v) +
  317. m_B[0][3][e] * Basis(0, 3, u, v) +
  318. m_B[3][0][e] * Basis(3, 0, u, v) +
  319. m_B[0][1][e] * Basis(0, 1, u, v) +
  320. m_B[0][2][e] * Basis(0, 2, u, v) +
  321. m_B[1][2][e] * Basis(1, 2, u, v) +
  322. m_B[2][1][e] * Basis(2, 1, u, v) +
  323. m_B[2][0][e] * Basis(2, 0, u, v) +
  324. m_B[1][0][e] * Basis(1, 0, u, v) +
  325. m_B[1][1][e] * Basis(1, 1, u, v));
  326. }
  327. }
  328. //-----------------------------------------------------------------------------
  329. // RDCubicBezierTriangle::Sample
  330. //-----------------------------------------------------------------------------
  331. void RDCubicBezierTriangle::Sample(DWORD dwDataType, double u, double v, const BYTE* const B[], BYTE *Q) const
  332. {
  333. double w = 1.0 - u - v;
  334. unsigned dwElements = 0;
  335. switch(dwDataType)
  336. {
  337. case D3DVSDT_FLOAT4:
  338. ++dwElements;
  339. case D3DVSDT_FLOAT3:
  340. ++dwElements;
  341. case D3DVSDT_FLOAT2:
  342. ++dwElements;
  343. case D3DVSDT_FLOAT1:
  344. ++dwElements;
  345. {
  346. for(unsigned e = 0; e < dwElements; ++e)
  347. {
  348. ((FLOAT*)Q)[e] = FLOAT(w * double(((FLOAT*)B[0])[e]) + v * double(((FLOAT*)B[1])[e]) + u * double(((FLOAT*)B[2])[e]));
  349. }
  350. }
  351. break;
  352. case D3DVSDT_D3DCOLOR:
  353. case D3DVSDT_UBYTE4:
  354. dwElements = 4;
  355. {
  356. for(unsigned e = 0; e < 4; ++e)
  357. {
  358. int t = int(w * double(B[0][e]) + v * double(B[1][e]) + u * double(B[2][e]));
  359. Q[e] = BYTE(t < 0 ? 0 : (t > 255 ? 255 : t));
  360. }
  361. }
  362. break;
  363. case D3DVSDT_SHORT4:
  364. dwElements += 2;
  365. case D3DVSDT_SHORT2:
  366. dwElements += 2;
  367. {
  368. for(unsigned e = 0; e < dwElements; ++e)
  369. {
  370. ((SHORT*)Q)[e] = SHORT(w * double(((SHORT*)B[0])[e]) + v * double(((SHORT*)B[1])[e]) + u * double(((SHORT*)B[2])[e]));
  371. }
  372. }
  373. break;
  374. default:
  375. _ASSERT(FALSE, "Ununderstood vertex element data type");
  376. }
  377. }
  378. //-----------------------------------------------------------------------------
  379. // RDNPatch::RDNPatch
  380. //-----------------------------------------------------------------------------
  381. RDNPatch::RDNPatch(const FLOAT* const pV[], const FLOAT* const pN[],
  382. const DWORD PositionOrder, const DWORD NormalOrder)
  383. {
  384. _ASSERT((PositionOrder == D3DORDER_LINEAR) || (PositionOrder == D3DORDER_CUBIC),
  385. "Unsupported position order in NPatch");
  386. _ASSERT((NormalOrder == D3DORDER_LINEAR) || (NormalOrder == D3DORDER_QUADRATIC),
  387. "Unsupported normal order in NPatch");
  388. m_PositionOrder = PositionOrder;
  389. m_NormalOrder = NormalOrder;
  390. // Assign corner points
  391. m_B[0][0][0] = double(pV[0][0]);
  392. m_B[0][0][1] = double(pV[0][1]);
  393. m_B[0][0][2] = double(pV[0][2]);
  394. m_B[0][3][0] = double(pV[1][0]);
  395. m_B[0][3][1] = double(pV[1][1]);
  396. m_B[0][3][2] = double(pV[1][2]);
  397. m_B[3][0][0] = double(pV[2][0]);
  398. m_B[3][0][1] = double(pV[2][1]);
  399. m_B[3][0][2] = double(pV[2][2]);
  400. if (PositionOrder == D3DORDER_CUBIC)
  401. {
  402. // Compute edge control points
  403. ComputeEdgeControlPoint(0, 1, pV, pN, 0, 1);
  404. ComputeEdgeControlPoint(1, 0, pV, pN, 0, 2);
  405. ComputeEdgeControlPoint(1, 2, pV, pN, 1, 2);
  406. ComputeEdgeControlPoint(2, 1, pV, pN, 2, 1);
  407. ComputeEdgeControlPoint(2, 0, pV, pN, 2, 0);
  408. ComputeEdgeControlPoint(0, 2, pV, pN, 1, 0);
  409. // Compute central control point
  410. m_B[1][1][0] = (m_B[2][0][0] + m_B[1][0][0] + m_B[0][2][0] + m_B[0][1][0] + m_B[2][1][0] + m_B[1][2][0]) / 4.0 -
  411. (m_B[3][0][0] + m_B[0][3][0] + m_B[0][0][0]) / 6.0;
  412. m_B[1][1][1] = (m_B[2][0][1] + m_B[1][0][1] + m_B[0][2][1] + m_B[0][1][1] + m_B[2][1][1] + m_B[1][2][1]) / 4.0 -
  413. (m_B[3][0][1] + m_B[0][3][1] + m_B[0][0][1]) / 6.0;
  414. m_B[1][1][2] = (m_B[2][0][2] + m_B[1][0][2] + m_B[0][2][2] + m_B[0][1][2] + m_B[2][1][2] + m_B[1][2][2]) / 4.0 -
  415. (m_B[3][0][2] + m_B[0][3][2] + m_B[0][0][2]) / 6.0;
  416. }
  417. if (NormalOrder == D3DORDER_QUADRATIC)
  418. {
  419. // Compute central control point
  420. Normalize(*(RDVECTOR3*)pN[0]);
  421. Normalize(*(RDVECTOR3*)pN[1]);
  422. Normalize(*(RDVECTOR3*)pN[2]);
  423. m_N002 = *(RDVECTOR3*)pN[0];
  424. m_N020 = *(RDVECTOR3*)pN[1];
  425. m_N200 = *(RDVECTOR3*)pN[2];
  426. ComputeNormalControlPoint(&m_N110, 1, 2, pV, pN);
  427. ComputeNormalControlPoint(&m_N101, 2, 0, pV, pN);
  428. ComputeNormalControlPoint(&m_N011, 0, 1, pV, pN);
  429. }
  430. }
  431. //-----------------------------------------------------------------------------
  432. // RDNPatch::SamplePosition
  433. //-----------------------------------------------------------------------------
  434. void RDNPatch::SamplePosition(double u, double v, FLOAT *Q) const
  435. {
  436. if (m_PositionOrder == D3DORDER_CUBIC)
  437. RDCubicBezierTriangle::SamplePosition(u, v, Q);
  438. else
  439. {
  440. double w = 1.0 - u - v;
  441. Q[0] = m_B[0][0][0] * w + m_B[0][3][0] * v + m_B[3][0][0] * u;
  442. Q[1] = m_B[0][0][1] * w + m_B[0][3][1] * v + m_B[3][0][1] * u;
  443. Q[2] = m_B[0][0][2] * w + m_B[0][3][2] * v + m_B[3][0][2] * u;
  444. }
  445. }
  446. //-----------------------------------------------------------------------------
  447. // RDNPatch::SampleNormal
  448. //-----------------------------------------------------------------------------
  449. void RDNPatch::SampleNormal(double u, double v, const BYTE* const B[], FLOAT *Q) const
  450. {
  451. if (m_NormalOrder == D3DORDER_LINEAR)
  452. RDCubicBezierTriangle::Sample(D3DVSDT_FLOAT3, u, v, B, (BYTE*)Q);
  453. else
  454. {
  455. // Computed by article "Curved PN Triangles" (Chas Boyd, ...)
  456. double w = 1.0 - u - v;
  457. double ww = w*w;
  458. double uu = u*u;
  459. double vv = v*v;
  460. double uv = u*v;
  461. double wu = w*u;
  462. double wv = w*v;
  463. Q[0] = m_N200.x * uu + m_N020.x * vv + m_N002.x * ww + m_N110.x * uv + m_N011.x * wv + m_N101.x * wu;
  464. Q[1] = m_N200.y * uu + m_N020.y * vv + m_N002.y * ww + m_N110.y * uv + m_N011.y * wv + m_N101.y * wu;
  465. Q[2] = m_N200.z * uu + m_N020.z * vv + m_N002.z * ww + m_N110.z * uv + m_N011.z * wv + m_N101.z * wu;
  466. Normalize(*(RDVECTOR3*)Q);
  467. }
  468. }
  469. //-----------------------------------------------------------------------------
  470. // RDNPatch::ComputeNormalControlPoint
  471. //-----------------------------------------------------------------------------
  472. void RDNPatch::ComputeNormalControlPoint(RDVECTOR3* cp, unsigned i, unsigned j,
  473. const FLOAT* const pV[],
  474. const FLOAT* const pN[])
  475. {
  476. RDVECTOR3 Pji, Nij;
  477. SubtractVector(*(RDVECTOR3*)pV[j], *(RDVECTOR3*)pV[i], Pji);
  478. AddVector(*(RDVECTOR3*)pN[j], *(RDVECTOR3*)pN[i], Nij);
  479. FLOAT v = 2.0f * DotProduct(Pji, Nij) / DotProduct(Pji, Pji);
  480. SubtractVector(Nij, ScaleVector(Pji, v), *cp);
  481. }
  482. //-----------------------------------------------------------------------------
  483. // RDNPatch::ComputeEdgeControlPoint
  484. //-----------------------------------------------------------------------------
  485. void RDNPatch::ComputeEdgeControlPoint(unsigned a, unsigned b, const FLOAT* const pV[], const FLOAT* const pN[], unsigned u, unsigned v)
  486. {
  487. static const double Tension = 1.0 / 3.0;
  488. double t, Edge[3];
  489. Edge[0] = double(pV[b][0]) - double(pV[a][0]);
  490. Edge[1] = double(pV[b][1]) - double(pV[a][1]);
  491. Edge[2] = double(pV[b][2]) - double(pV[a][2]);
  492. t = Edge[0] * double(pN[a][0]) + Edge[1] * double(pN[a][1]) + Edge[2] * double(pN[a][2]);
  493. m_B[u][v][0] = double(pV[a][0]) + (Edge[0] - t * double(pN[a][0])) * Tension;
  494. m_B[u][v][1] = double(pV[a][1]) + (Edge[1] - t * double(pN[a][1])) * Tension;
  495. m_B[u][v][2] = double(pV[a][2]) + (Edge[2] - t * double(pN[a][2])) * Tension;
  496. }