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.

1117 lines
46 KiB

  1. /*============================================================================
  2. *
  3. * Copyright (C) 2001 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: npatch.cpp
  6. * Content: Consersion of NPatches to Rect-Patches
  7. *
  8. ****************************************************************************/
  9. #include "pch.cpp"
  10. #pragma hdrstop
  11. //-----------------------------------------------------------------------------
  12. UINT CVertexPointer::Stride[__NUMELEMENTS];
  13. UINT CVertexPointer::NumUsedElements;
  14. UINT CVertexPointer::DataType[__NUMELEMENTS];
  15. //-----------------------------------------------------------------------------
  16. static const float Tension = 1.0f/3.0f;
  17. static const float OneOver3 = 1.0f/3.0f;
  18. //-----------------------------------------------------------------------------
  19. struct UVW
  20. {
  21. float u, v, w, uu, vv, ww, uv, uw, vw;
  22. };
  23. static UVW g_uvw[10];
  24. //-----------------------------------------------------------------------------
  25. CNPatch2TriPatch::CNPatch2TriPatch()
  26. {
  27. memset(this, 0, sizeof(this));
  28. // Write only streams with RTPatches usage
  29. for (int i=0; i < __NUMELEMENTS; i++)
  30. m_pOutStream[i] = new CTLStream(TRUE, D3DUSAGE_RTPATCHES);
  31. int k = 0;
  32. for(int vv = 3; vv >= 0; --vv)
  33. for(int uu = 0; uu < 4 - vv; ++uu)
  34. {
  35. int ww = 3 - uu - vv;
  36. float u = uu * OneOver3;
  37. float v = vv * OneOver3;
  38. float w = ww * OneOver3;
  39. g_uvw[k].u = u;
  40. g_uvw[k].v = v;
  41. g_uvw[k].w = w;
  42. g_uvw[k].uu = u*u;
  43. g_uvw[k].vv = v*v;
  44. g_uvw[k].ww = w*w;
  45. g_uvw[k].uv = u*v;
  46. g_uvw[k].uw = u*w;
  47. g_uvw[k].vw = v*w;
  48. k++;
  49. }
  50. }
  51. //-----------------------------------------------------------------------------
  52. void ComputeNormalControlPoint(D3DVECTOR* cp,
  53. float* pVi, float* pVj,
  54. float* pNi, float* pNj)
  55. {
  56. D3DVECTOR Pji;
  57. D3DVECTOR Nij;
  58. VecSub(*(D3DVECTOR*)pVj, *(D3DVECTOR*)pVi, Pji);
  59. VecAdd(*(D3DVECTOR*)pNj, *(D3DVECTOR*)pNi, Nij);
  60. FLOAT v = 2.0f * VecDot(Pji, Nij) / VecDot(Pji, Pji);
  61. Pji.x *= v;
  62. Pji.y *= v;
  63. Pji.z *= v;
  64. VecSub(Nij, Pji, *cp);
  65. // Now go from polynomial coefficients to Bezier control points
  66. cp->x *= 0.5f;
  67. cp->y *= 0.5f;
  68. cp->z *= 0.5f;
  69. }
  70. //-----------------------------------------------------------------------------
  71. CNPatch2TriPatch::~CNPatch2TriPatch()
  72. {
  73. for (int i=0; i < __NUMELEMENTS; i++)
  74. delete m_pOutStream[i];
  75. }
  76. //-----------------------------------------------------------------------------
  77. // Convert NPatch to Rect-Patch:
  78. //
  79. void CNPatch2TriPatch::MakeRectPatch(const CVertexPointer& pV0,
  80. const CVertexPointer& pV2,
  81. const CVertexPointer& pV1)
  82. {
  83. float t, Edge[3], B[10][3];
  84. float n0[3];
  85. float n1[3];
  86. float n2[3];
  87. float *p0 = (float*)pV0.pData[m_PositionIndex];
  88. float *p1 = (float*)pV1.pData[m_PositionIndex];
  89. float *p2 = (float*)pV2.pData[m_PositionIndex];
  90. n0[0] = ((float*)pV0.pData[m_NormalIndex])[0];
  91. n0[1] = ((float*)pV0.pData[m_NormalIndex])[1];
  92. n0[2] = ((float*)pV0.pData[m_NormalIndex])[2];
  93. n1[0] = ((float*)pV1.pData[m_NormalIndex])[0];
  94. n1[1] = ((float*)pV1.pData[m_NormalIndex])[1];
  95. n1[2] = ((float*)pV1.pData[m_NormalIndex])[2];
  96. n2[0] = ((float*)pV2.pData[m_NormalIndex])[0];
  97. n2[1] = ((float*)pV2.pData[m_NormalIndex])[1];
  98. n2[2] = ((float*)pV2.pData[m_NormalIndex])[2];
  99. // Coefficients to interpolate quadratic normals
  100. D3DVECTOR N002;
  101. D3DVECTOR N020;
  102. D3DVECTOR N200;
  103. D3DVECTOR N110;
  104. D3DVECTOR N101;
  105. D3DVECTOR N011;
  106. // Convert NPatch to Tri-Patch first
  107. if (m_PositionOrder == D3DORDER_CUBIC)
  108. {
  109. B[0][0] = p0[0];
  110. B[0][1] = p0[1];
  111. B[0][2] = p0[2];
  112. B[6][0] = p1[0];
  113. B[6][1] = p1[1];
  114. B[6][2] = p1[2];
  115. B[9][0] = p2[0];
  116. B[9][1] = p2[1];
  117. B[9][2] = p2[2];
  118. Edge[0] = p1[0] - p0[0];
  119. Edge[1] = p1[1] - p0[1];
  120. Edge[2] = p1[2] - p0[2];
  121. t = Edge[0] * n0[0] + Edge[1] * n0[1] + Edge[2] * n0[2];
  122. B[1][0] = p0[0] + (Edge[0] - n0[0] * t) * Tension;
  123. B[1][1] = p0[1] + (Edge[1] - n0[1] * t) * Tension;
  124. B[1][2] = p0[2] + (Edge[2] - n0[2] * t) * Tension;
  125. Edge[0] = p0[0] - p1[0];
  126. Edge[1] = p0[1] - p1[1];
  127. Edge[2] = p0[2] - p1[2];
  128. t = Edge[0] * n1[0] + Edge[1] * n1[1] + Edge[2] * n1[2];
  129. B[3][0] = p1[0] + (Edge[0] - n1[0] * t) * Tension;
  130. B[3][1] = p1[1] + (Edge[1] - n1[1] * t) * Tension;
  131. B[3][2] = p1[2] + (Edge[2] - n1[2] * t) * Tension;
  132. Edge[0] = p2[0] - p1[0];
  133. Edge[1] = p2[1] - p1[1];
  134. Edge[2] = p2[2] - p1[2];
  135. t = Edge[0] * n1[0] + Edge[1] * n1[1] + Edge[2] * n1[2];
  136. B[7][0] = p1[0] + (Edge[0] - n1[0] * t) * Tension;
  137. B[7][1] = p1[1] + (Edge[1] - n1[1] * t) * Tension;
  138. B[7][2] = p1[2] + (Edge[2] - n1[2] * t) * Tension;
  139. Edge[0] = p1[0] - p2[0];
  140. Edge[1] = p1[1] - p2[1];
  141. Edge[2] = p1[2] - p2[2];
  142. t = Edge[0] * n2[0] + Edge[1] * n2[1] + Edge[2] * n2[2];
  143. B[8][0] = p2[0] + (Edge[0] - n2[0] * t) * Tension;
  144. B[8][1] = p2[1] + (Edge[1] - n2[1] * t) * Tension;
  145. B[8][2] = p2[2] + (Edge[2] - n2[2] * t) * Tension;
  146. Edge[0] = p2[0] - p0[0];
  147. Edge[1] = p2[1] - p0[1];
  148. Edge[2] = p2[2] - p0[2];
  149. t = Edge[0] * n0[0] + Edge[1] * n0[1] + Edge[2] * n0[2];
  150. B[2][0] = p0[0] + (Edge[0] - n0[0] * t) * Tension;
  151. B[2][1] = p0[1] + (Edge[1] - n0[1] * t) * Tension;
  152. B[2][2] = p0[2] + (Edge[2] - n0[2] * t) * Tension;
  153. Edge[0] = p0[0] - p2[0];
  154. Edge[1] = p0[1] - p2[1];
  155. Edge[2] = p0[2] - p2[2];
  156. t = Edge[0] * n2[0] + Edge[1] * n2[1] + Edge[2] * n2[2];
  157. B[5][0] = p2[0] + (Edge[0] - n2[0] * t) * Tension;
  158. B[5][1] = p2[1] + (Edge[1] - n2[1] * t) * Tension;
  159. B[5][2] = p2[2] + (Edge[2] - n2[2] * t) * Tension;
  160. B[4][0] = (B[1][0] + B[2][0] + B[3][0] + B[5][0] + B[7][0] + B[8][0]) / 4.0f - (B[0][0] + B[6][0] + B[9][0]) / 6.0f;
  161. B[4][1] = (B[1][1] + B[2][1] + B[3][1] + B[5][1] + B[7][1] + B[8][1]) / 4.0f - (B[0][1] + B[6][1] + B[9][1]) / 6.0f;
  162. B[4][2] = (B[1][2] + B[2][2] + B[3][2] + B[5][2] + B[7][2] + B[8][2]) / 4.0f - (B[0][2] + B[6][2] + B[9][2]) / 6.0f;
  163. }
  164. if (m_NormalOrder == D3DORDER_QUADRATIC)
  165. {
  166. // Compute central control point
  167. if (m_bNormalizeNormals)
  168. {
  169. VecNormalizeFast(*n0);
  170. VecNormalizeFast(*n1);
  171. VecNormalizeFast(*n2);
  172. }
  173. N002 = *(D3DVECTOR*)n1;
  174. N020 = *(D3DVECTOR*)n0;
  175. N200 = *(D3DVECTOR*)n2;
  176. // Compute edge control points
  177. ComputeNormalControlPoint(&N110, p0, p2, n0, n2);
  178. ComputeNormalControlPoint(&N101, p2, p1, n2, n1);
  179. ComputeNormalControlPoint(&N011, p1, p0, n1, n0);
  180. }
  181. float CP[__NUMELEMENTS*4][10]; // Computed tri-patch control pointes
  182. int iCP; // Float value index in the control point array
  183. for(int k = 0; k < 10; k++)
  184. {
  185. iCP = 0;
  186. const float U = g_uvw[k].u;
  187. const float V = g_uvw[k].v;
  188. const float W = g_uvw[k].w;
  189. for (UINT iElement=0; iElement < CVertexPointer::NumUsedElements; iElement++)
  190. {
  191. if (iElement == m_PositionIndex)
  192. {
  193. if (m_PositionOrder == D3DORDER_CUBIC)
  194. {
  195. CP[iCP++][k] = B[k][0];
  196. CP[iCP++][k] = B[k][1];
  197. CP[iCP++][k] = B[k][2];
  198. }
  199. else
  200. {
  201. CP[iCP++][k] = p2[0] * U + p0[0] * V + p1[0] * W;
  202. CP[iCP++][k] = p2[1] * U + p0[1] * V + p1[1] * W;
  203. CP[iCP++][k] = p2[2] * U + p0[2] * V + p1[2] * W;
  204. }
  205. }
  206. else
  207. if (iElement == m_NormalIndex)
  208. {
  209. if (m_NormalOrder == D3DORDER_QUADRATIC)
  210. {
  211. D3DVECTOR Q;
  212. // Do degree elevation from quadratic to cubic
  213. switch (k)
  214. {
  215. case 0:
  216. Q.x = N020.x;
  217. Q.y = N020.y;
  218. Q.z = N020.z;
  219. break;
  220. case 1:
  221. Q.x = (2.0f*N011.x + N020.x) * OneOver3;
  222. Q.y = (2.0f*N011.y + N020.y) * OneOver3;
  223. Q.z = (2.0f*N011.z + N020.z) * OneOver3;
  224. break;
  225. case 2:
  226. Q.x = (2.0f*N110.x + N020.x) * OneOver3;
  227. Q.y = (2.0f*N110.y + N020.y) * OneOver3;
  228. Q.z = (2.0f*N110.z + N020.z) * OneOver3;
  229. break;
  230. case 3:
  231. Q.x = (2.0f*N011.x + N002.x) * OneOver3;
  232. Q.y = (2.0f*N011.y + N002.y) * OneOver3;
  233. Q.z = (2.0f*N011.z + N002.z) * OneOver3;
  234. break;
  235. case 4:
  236. Q.x = (N011.x + N101.x + N110.x) * OneOver3;
  237. Q.y = (N011.y + N101.y + N110.y) * OneOver3;
  238. Q.z = (N011.z + N101.z + N110.z) * OneOver3;
  239. break;
  240. case 5:
  241. Q.x = (2.0f*N110.x + N200.x) * OneOver3;
  242. Q.y = (2.0f*N110.y + N200.y) * OneOver3;
  243. Q.z = (2.0f*N110.z + N200.z) * OneOver3;
  244. break;
  245. case 6:
  246. Q.x = N002.x;
  247. Q.y = N002.y;
  248. Q.z = N002.z;
  249. break;
  250. case 7:
  251. Q.x = (2.0f*N101.x + N002.x) * OneOver3;
  252. Q.y = (2.0f*N101.y + N002.y) * OneOver3;
  253. Q.z = (2.0f*N101.z + N002.z) * OneOver3;
  254. break;
  255. case 8:
  256. Q.x = (2.0f*N101.x + N200.x) * OneOver3;
  257. Q.y = (2.0f*N101.y + N200.y) * OneOver3;
  258. Q.z = (2.0f*N101.z + N200.z) * OneOver3;
  259. break;
  260. case 9:
  261. Q.x = N200.x;
  262. Q.y = N200.y;
  263. Q.z = N200.z;
  264. break;
  265. }
  266. CP[iCP++][k] = Q.x;
  267. CP[iCP++][k] = Q.y;
  268. CP[iCP++][k] = Q.z;
  269. }
  270. else
  271. {
  272. CP[iCP++][k] = n2[0] * U + n0[0] * V + n1[0] * W;
  273. CP[iCP++][k] = n2[1] * U + n0[1] * V + n1[1] * W;
  274. CP[iCP++][k] = n2[2] * U + n0[2] * V + n1[2] * W;
  275. }
  276. }
  277. else
  278. {
  279. switch(CVertexPointer::DataType[iElement])
  280. {
  281. case D3DVSDT_FLOAT1:
  282. CP[iCP++][k] = ((float*)pV2.pData[iElement])[0] * U +
  283. ((float*)pV0.pData[iElement])[0] * V +
  284. ((float*)pV1.pData[iElement])[0] * W;
  285. break;
  286. case D3DVSDT_FLOAT2:
  287. CP[iCP++][k] = ((float*)pV2.pData[iElement])[0] * U +
  288. ((float*)pV0.pData[iElement])[0] * V +
  289. ((float*)pV1.pData[iElement])[0] * W;
  290. CP[iCP++][k] = ((float*)pV2.pData[iElement])[1] * U +
  291. ((float*)pV0.pData[iElement])[1] * V +
  292. ((float*)pV1.pData[iElement])[1] * W;
  293. break;
  294. case D3DVSDT_FLOAT3:
  295. CP[iCP++][k] = ((float*)pV2.pData[iElement])[0] * U +
  296. ((float*)pV0.pData[iElement])[0] * V +
  297. ((float*)pV1.pData[iElement])[0] * W;
  298. CP[iCP++][k] = ((float*)pV2.pData[iElement])[1] * U +
  299. ((float*)pV0.pData[iElement])[1] * V +
  300. ((float*)pV1.pData[iElement])[1] * W;
  301. CP[iCP++][k] = ((float*)pV2.pData[iElement])[2] * U +
  302. ((float*)pV0.pData[iElement])[2] * V +
  303. ((float*)pV1.pData[iElement])[2] * W;
  304. break;
  305. case D3DVSDT_FLOAT4:
  306. CP[iCP++][k] = ((float*)pV2.pData[iElement])[0] * U +
  307. ((float*)pV0.pData[iElement])[0] * V +
  308. ((float*)pV1.pData[iElement])[0] * W;
  309. CP[iCP++][k] = ((float*)pV2.pData[iElement])[1] * U +
  310. ((float*)pV0.pData[iElement])[1] * V +
  311. ((float*)pV1.pData[iElement])[1] * W;
  312. CP[iCP++][k] = ((float*)pV2.pData[iElement])[2] * U +
  313. ((float*)pV0.pData[iElement])[2] * V +
  314. ((float*)pV1.pData[iElement])[2] * W;
  315. CP[iCP++][k] = ((float*)pV2.pData[iElement])[3] * U +
  316. ((float*)pV0.pData[iElement])[3] * V +
  317. ((float*)pV1.pData[iElement])[3] * W;
  318. break;
  319. case D3DVSDT_D3DCOLOR:
  320. case D3DVSDT_UBYTE4:
  321. DWORD c;
  322. c = *(DWORD*)pV0.pData[iElement];
  323. float r[3], g[3], b[3], a[3];
  324. r[0] = float(c & 0xFF);
  325. g[0] = float((c >> 8) & 0xFF);
  326. b[0] = float((c >> 16) & 0xFF);
  327. a[0] = float((c >> 24) & 0xFF);
  328. c = *(DWORD*)pV1.pData[iElement];
  329. r[1] = float(c & 0xFF);
  330. g[1] = float((c >> 8) & 0xFF);
  331. b[1] = float((c >> 16) & 0xFF);
  332. a[1] = float((c >> 24) & 0xFF);
  333. c = *(DWORD*)pV2.pData[iElement];
  334. r[2] = float(c & 0xFF);
  335. g[2] = float((c >> 8) & 0xFF);
  336. b[2] = float((c >> 16) & 0xFF);
  337. a[2] = float((c >> 24) & 0xFF);
  338. CP[iCP++][k] = r[2] * U + r[0] * V + r[1] * W;
  339. CP[iCP++][k] = g[2] * U + g[0] * V + g[1] * W;
  340. CP[iCP++][k] = b[2] * U + b[0] * V + b[1] * W;
  341. CP[iCP++][k] = a[2] * U + a[0] * V + a[1] * W;
  342. break;
  343. case D3DVSDT_SHORT2:
  344. CP[iCP++][k]= (float)(
  345. ((short*)pV2.pData[iElement])[0] * U +
  346. ((short*)pV0.pData[iElement])[0] * V +
  347. ((short*)pV1.pData[iElement])[0] * W);
  348. CP[iCP++][k] = (float)(
  349. ((short*)pV2.pData[iElement])[1] * U +
  350. ((short*)pV0.pData[iElement])[1] * V +
  351. ((short*)pV1.pData[iElement])[1] * W);
  352. break;
  353. case D3DVSDT_SHORT4:
  354. CP[iCP++][k] = (float)(
  355. ((short*)pV2.pData[iElement])[0] * U +
  356. ((short*)pV0.pData[iElement])[0] * V +
  357. ((short*)pV1.pData[iElement])[0] * W);
  358. CP[iCP++][k] = (float)(
  359. ((short*)pV2.pData[iElement])[1] * U +
  360. ((short*)pV0.pData[iElement])[1] * V +
  361. ((short*)pV1.pData[iElement])[1] * W);
  362. CP[iCP++][k] = (float)(
  363. ((short*)pV2.pData[iElement])[2] * U +
  364. ((short*)pV0.pData[iElement])[2] * V +
  365. ((short*)pV1.pData[iElement])[2] * W);
  366. CP[iCP++][k] = (float)(
  367. ((short*)pV2.pData[iElement])[3] * U +
  368. ((short*)pV0.pData[iElement])[3] * V +
  369. ((short*)pV1.pData[iElement])[3] * W);
  370. break;
  371. default: DXGASSERT(FALSE);
  372. }
  373. }
  374. }
  375. }
  376. // Now convert Tri-Patch to Rect-Patch by transforming 10 tri-patch control
  377. // points to 16 rect-patch control points
  378. float CPR[16][__NUMELEMENTS*4]; // Computed rect-patch control pointes
  379. {
  380. for (int i=0; i < iCP; i++)
  381. {
  382. // First row - copy first point 4 times
  383. CPR[0][i] = CPR[1][i] =
  384. CPR[2][i] = CPR[3][i] = CP[i][0];
  385. // 2nd row
  386. float v1 = CP[i][1];
  387. float v2 = CP[i][2];
  388. CPR[ 4][i] = v1;
  389. CPR[ 5][i] = (v1 * 2.0f + v2 ) * OneOver3;
  390. CPR[ 6][i] = (v1 + v2 * 2.0f) * OneOver3;
  391. CPR[ 7][i] = v2;
  392. // 3rd row
  393. CPR[ 8][i] = CP[i][3];
  394. CPR[ 9][i] = (CP[i][3] + CP[i][4] * 2.0f) * OneOver3;
  395. CPR[10][i] = (CP[i][4] * 2.0f + CP[i][5] ) * OneOver3;
  396. CPR[11][i] = CP[i][5];
  397. // 4th row - copy all elements
  398. CPR[12][i] = CP[i][6];
  399. CPR[13][i] = CP[i][7];
  400. CPR[14][i] = CP[i][8];
  401. CPR[15][i] = CP[i][9];
  402. }
  403. }
  404. // Output the result
  405. {
  406. for (int i=0; i < 16; i++)
  407. {
  408. UINT k = 0;
  409. for (UINT iElement=0; iElement < CVertexPointer::NumUsedElements; iElement++)
  410. {
  411. float* pout = (float*)m_OutVertex.pData[iElement];
  412. switch(CVertexPointer::DataType[iElement])
  413. {
  414. case D3DVSDT_FLOAT1:
  415. pout[0] = CPR[i][k++];
  416. break;
  417. case D3DVSDT_FLOAT2:
  418. pout[0] = CPR[i][k++];
  419. pout[1] = CPR[i][k++];
  420. break;
  421. case D3DVSDT_FLOAT3:
  422. pout[0] = CPR[i][k++];
  423. pout[1] = CPR[i][k++];
  424. pout[2] = CPR[i][k++];
  425. break;
  426. case D3DVSDT_FLOAT4:
  427. pout[0] = CPR[i][k++];
  428. pout[1] = CPR[i][k++];
  429. pout[2] = CPR[i][k++];
  430. pout[3] = CPR[i][k++];
  431. break;
  432. case D3DVSDT_D3DCOLOR:
  433. case D3DVSDT_UBYTE4:
  434. {
  435. DWORD c;
  436. float r = CPR[i][k++];
  437. float g = CPR[i][k++];
  438. float b = CPR[i][k++];
  439. float a = CPR[i][k++];
  440. c = DWORD(r);
  441. c |= DWORD(g) << 8;
  442. c |= DWORD(b) << 16;
  443. c |= DWORD(a) << 24;
  444. *(DWORD*)pout = c;
  445. }
  446. break;
  447. case D3DVSDT_SHORT2:
  448. ((short*)pout)[0] = (short)(CPR[i][k++]);
  449. ((short*)pout)[1] = (short)(CPR[i][k++]);
  450. break;
  451. case D3DVSDT_SHORT4:
  452. ((short*)pout)[0] = (short)(CPR[i][k++]);
  453. ((short*)pout)[1] = (short)(CPR[i][k++]);
  454. ((short*)pout)[2] = (short)(CPR[i][k++]);
  455. ((short*)pout)[3] = (short)(CPR[i][k++]);
  456. break;
  457. default: DXGASSERT(FALSE);
  458. }
  459. }
  460. m_OutVertex++;
  461. }
  462. }
  463. }
  464. //-----------------------------------------------------------------------------
  465. void DrawPatches(CD3DHal* pDevice, UINT PrimitiveCount)
  466. {
  467. // Unlock output vertex buffers
  468. if (D3DVSD_ISLEGACY(pDevice->m_dwCurrentShaderHandle))
  469. {
  470. pDevice->m_pConvObj->m_pOutStream[0]->m_pVB->Unlock();
  471. }
  472. else
  473. {
  474. CVDeclaration* pDecl = &pDevice->m_pCurrentShader->m_Declaration;
  475. CVStreamDecl* pStreamDecl = pDevice->m_pCurrentShader->m_Declaration.m_pActiveStreams;
  476. while (pStreamDecl)
  477. {
  478. pDevice->m_pConvObj->m_pOutStream[pStreamDecl->m_dwStreamIndex]->m_pVB->Unlock();
  479. pStreamDecl = (CVStreamDecl*)pStreamDecl->m_pNext;
  480. }
  481. }
  482. // Draw rect patches
  483. float numSegs[4];
  484. numSegs[0] =
  485. numSegs[1] =
  486. numSegs[2] =
  487. numSegs[3] = *(float*)&pDevice->rstates[D3DRS_PATCHSEGMENTS];
  488. D3DRECTPATCH_INFO info;
  489. info.StartVertexOffsetWidth = pDevice->m_pConvObj->m_FirstVertex;
  490. info.StartVertexOffsetHeight = 0;
  491. info.Width = 4;
  492. info.Height = 4;
  493. info.Stride = 4; // verticies to next row of verticies
  494. info.Basis = D3DBASIS_BEZIER;
  495. info.Order = D3DORDER_CUBIC;
  496. for (UINT i = PrimitiveCount; i > 0; i--)
  497. {
  498. pDevice->DrawRectPatch(0, numSegs, &info);
  499. info.StartVertexOffsetWidth += 16;
  500. }
  501. // Restore input vertex streams
  502. if (D3DVSD_ISLEGACY(pDevice->m_dwCurrentShaderHandle))
  503. {
  504. // Always need to call SetStreamSource to decrease reference count of
  505. // the internal VB buffer
  506. pDevice->SetStreamSource(0, pDevice->m_pConvObj->m_InpStream[0].m_pVB,
  507. CVertexPointer::Stride[0]);
  508. if (pDevice->m_pConvObj->m_InpStream[0].m_pVB)
  509. {
  510. // Remove additional ref count, because the stream is set
  511. // second time
  512. pDevice->m_pConvObj->m_InpStream[0].m_pVB->Release();
  513. pDevice->m_pConvObj->m_InpStream[0].m_pVB = NULL;
  514. }
  515. }
  516. else
  517. {
  518. CVDeclaration* pDecl = &pDevice->m_pCurrentShader->m_Declaration;
  519. CVStreamDecl* pStreamDecl = pDevice->m_pCurrentShader->m_Declaration.m_pActiveStreams;
  520. while (pStreamDecl)
  521. {
  522. UINT si = pStreamDecl->m_dwStreamIndex;
  523. UINT Stride = pStreamDecl->m_dwStride;
  524. CVStream* pStream = &pDevice->m_pConvObj->m_InpStream[si];
  525. // Always need to call SetStreamSource to decrease reference count
  526. // of the internal VB buffer
  527. pDevice->SetStreamSource(si, pStream->m_pVB, Stride);
  528. if (pStream->m_pVB)
  529. {
  530. // Remove additional ref count, because the stream is set second
  531. // time
  532. pStream->m_pVB->Release();
  533. pStream->m_pVB = NULL;
  534. }
  535. pStreamDecl = (CVStreamDecl*)pStreamDecl->m_pNext;
  536. }
  537. }
  538. }
  539. //-----------------------------------------------------------------------------
  540. void CD3DHal_DrawNPatch(CD3DBase* pBaseDevice, D3DPRIMITIVETYPE PrimitiveType,
  541. UINT StartVertex, UINT PrimitiveCount)
  542. {
  543. CD3DHal* pDevice = static_cast<CD3DHal*>(pBaseDevice);
  544. // Draw as usual for non-triangle primitive types
  545. if (PrimitiveType < D3DPT_TRIANGLELIST)
  546. {
  547. (*pDevice->m_pfnDrawPrimFromNPatch)(pBaseDevice, PrimitiveType,
  548. StartVertex, PrimitiveCount);
  549. // m_pfnDrawPrim could be switched to fast path, so we need to restore it
  550. pDevice->m_pfnDrawPrim = CD3DHal_DrawNPatch;
  551. return;
  552. }
  553. #if DBG
  554. UINT nVer = GETVERTEXCOUNT(PrimitiveType, PrimitiveCount);
  555. pDevice->ValidateDraw2(PrimitiveType, StartVertex, PrimitiveCount, nVer,
  556. FALSE);
  557. #endif
  558. pDevice->PrepareNPatchConversion(PrimitiveCount, StartVertex);
  559. // Go through triangles and generate tri-patches
  560. CNPatch2TriPatch* pConvObj = pDevice->m_pConvObj;
  561. switch( PrimitiveType )
  562. {
  563. case D3DPT_TRIANGLELIST:
  564. {
  565. for (UINT i = PrimitiveCount; i > 0; i--)
  566. {
  567. CVertexPointer pV0 = pConvObj->m_InpVertex;
  568. pConvObj->m_InpVertex++;
  569. CVertexPointer pV1 = pConvObj->m_InpVertex;
  570. pConvObj->m_InpVertex++;
  571. CVertexPointer pV2 = pConvObj->m_InpVertex;
  572. pConvObj->m_InpVertex++;
  573. pConvObj->MakeRectPatch(pV0, pV1, pV2);
  574. }
  575. }
  576. break;
  577. case D3DPT_TRIANGLESTRIP:
  578. {
  579. // Get initial vertex values.
  580. CVertexPointer pV0;
  581. CVertexPointer pV1 = pConvObj->m_InpVertex;
  582. pConvObj->m_InpVertex++;
  583. CVertexPointer pV2 = pConvObj->m_InpVertex;
  584. pConvObj->m_InpVertex++;
  585. for (UINT i =PrimitiveCount; i > 1; i -= 2)
  586. {
  587. pV0 = pV1;
  588. pV1 = pV2;
  589. pV2 = pConvObj->m_InpVertex;
  590. pConvObj->m_InpVertex++;
  591. pConvObj->MakeRectPatch(pV0, pV1, pV2);
  592. pV0 = pV1;
  593. pV1 = pV2;
  594. pV2 = pConvObj->m_InpVertex;
  595. pConvObj->m_InpVertex++;
  596. pConvObj->MakeRectPatch(pV0, pV2, pV1);
  597. }
  598. if (i > 0)
  599. {
  600. pV0 = pV1;
  601. pV1 = pV2;
  602. pV2 = pConvObj->m_InpVertex;
  603. pConvObj->MakeRectPatch(pV0, pV1, pV2);
  604. }
  605. }
  606. break;
  607. case D3DPT_TRIANGLEFAN:
  608. {
  609. CVertexPointer pV0;
  610. CVertexPointer pV1;
  611. CVertexPointer pV2;
  612. pV2 = pConvObj->m_InpVertex;
  613. pConvObj->m_InpVertex++;
  614. // Preload initial pV0.
  615. pV1 = pConvObj->m_InpVertex;
  616. pConvObj->m_InpVertex++;
  617. for (UINT i = PrimitiveCount; i > 0; i--)
  618. {
  619. pV0 = pV1;
  620. pV1 = pConvObj->m_InpVertex;
  621. pConvObj->m_InpVertex++;
  622. pConvObj->MakeRectPatch(pV0, pV1, pV2);
  623. }
  624. }
  625. break;
  626. default:
  627. DXGASSERT(FALSE);
  628. }
  629. pDevice->m_pDDI->SetWithinPrimitive(TRUE);
  630. DrawPatches(pDevice, PrimitiveCount);
  631. pDevice->m_pDDI->SetWithinPrimitive(FALSE);
  632. }
  633. //-----------------------------------------------------------------------------
  634. void CD3DHal_DrawIndexedNPatch(CD3DBase* pBaseDevice,
  635. D3DPRIMITIVETYPE PrimitiveType,
  636. UINT BaseIndex,
  637. UINT MinIndex, UINT NumVertices,
  638. UINT StartIndex,
  639. UINT PrimitiveCount)
  640. {
  641. CD3DHal* pDevice = static_cast<CD3DHal*>(pBaseDevice);
  642. // Draw as usual for non-triangle primitive types
  643. if (PrimitiveType < D3DPT_TRIANGLELIST)
  644. {
  645. (*pDevice->m_pfnDrawIndexedPrimFromNPatch)(pBaseDevice, PrimitiveType,
  646. BaseIndex, MinIndex, NumVertices,
  647. StartIndex, PrimitiveCount);
  648. // m_pfnDrawIndexedPrim could be switched to fast path, so we
  649. // need to restore it
  650. pDevice->m_pfnDrawIndexedPrim = CD3DHal_DrawIndexedNPatch;
  651. return;
  652. }
  653. #if DBG
  654. pDevice->ValidateDraw2(PrimitiveType, MinIndex + BaseIndex, PrimitiveCount, NumVertices,
  655. TRUE, StartIndex);
  656. #endif
  657. pDevice->PrepareNPatchConversion(PrimitiveCount, BaseIndex);
  658. // Go through triangles and generate tri-patches
  659. CNPatch2TriPatch* pConvObj = pDevice->m_pConvObj;
  660. if (pDevice->m_pIndexStream->m_dwStride == 2)
  661. {
  662. WORD* pIndices = (WORD*)pDevice->m_pIndexStream->Data() + StartIndex;
  663. switch( PrimitiveType )
  664. {
  665. case D3DPT_TRIANGLELIST:
  666. {
  667. for (UINT i = PrimitiveCount; i > 0; i--)
  668. {
  669. CVertexPointer pV0;
  670. CVertexPointer pV1;
  671. CVertexPointer pV2;
  672. pV0.SetVertex(pConvObj->m_InpVertex, (*pIndices++));
  673. pV1.SetVertex(pConvObj->m_InpVertex, (*pIndices++));
  674. pV2.SetVertex(pConvObj->m_InpVertex, (*pIndices++));
  675. pConvObj->MakeRectPatch(pV0, pV1, pV2);
  676. }
  677. }
  678. break;
  679. case D3DPT_TRIANGLESTRIP:
  680. {
  681. CVertexPointer pV0;
  682. CVertexPointer pV1;
  683. CVertexPointer pV2;
  684. // Get initial vertex values.
  685. pV1.SetVertex(pConvObj->m_InpVertex, (*pIndices++));
  686. pV2.SetVertex(pConvObj->m_InpVertex, (*pIndices++));
  687. for (UINT i = PrimitiveCount; i > 1; i -= 2)
  688. {
  689. pV0 = pV1;
  690. pV1 = pV2;
  691. pV2.SetVertex(pConvObj->m_InpVertex, (*pIndices++));
  692. pConvObj->MakeRectPatch(pV0, pV1, pV2);
  693. pV0 = pV1;
  694. pV1 = pV2;
  695. pV2.SetVertex(pConvObj->m_InpVertex, (*pIndices++));
  696. pConvObj->MakeRectPatch(pV0, pV2, pV1);
  697. }
  698. if (i > 0)
  699. {
  700. pV0 = pV1;
  701. pV1 = pV2;
  702. pV2.SetVertex(pConvObj->m_InpVertex, (*pIndices++));
  703. pConvObj->MakeRectPatch(pV0, pV1, pV2);
  704. }
  705. }
  706. break;
  707. case D3DPT_TRIANGLEFAN:
  708. {
  709. CVertexPointer pV1;
  710. CVertexPointer pV2;
  711. pV2.SetVertex(pConvObj->m_InpVertex, (*pIndices++));
  712. // Preload initial pV0.
  713. pV1.SetVertex(pConvObj->m_InpVertex, (*pIndices++));
  714. for (UINT i = PrimitiveCount; i > 0; i--)
  715. {
  716. CVertexPointer pV0 = pV1;
  717. pV1.SetVertex(pConvObj->m_InpVertex, (*pIndices++));
  718. pConvObj->MakeRectPatch(pV0, pV2, pV1);
  719. }
  720. }
  721. break;
  722. default:
  723. DXGASSERT(FALSE);
  724. }
  725. }
  726. else
  727. {
  728. DWORD* pIndices = (DWORD*)pDevice->m_pIndexStream->Data() + StartIndex;
  729. switch( PrimitiveType )
  730. {
  731. case D3DPT_TRIANGLELIST:
  732. {
  733. for (UINT i = PrimitiveCount; i > 0; i--)
  734. {
  735. CVertexPointer pV0;
  736. CVertexPointer pV1;
  737. CVertexPointer pV2;
  738. pV0.SetVertex(pConvObj->m_InpVertex, (*pIndices++));
  739. pV1.SetVertex(pConvObj->m_InpVertex, (*pIndices++));
  740. pV2.SetVertex(pConvObj->m_InpVertex, (*pIndices++));
  741. pConvObj->MakeRectPatch(pV0, pV1, pV2);
  742. }
  743. }
  744. break;
  745. case D3DPT_TRIANGLESTRIP:
  746. {
  747. CVertexPointer pV0;
  748. CVertexPointer pV1;
  749. CVertexPointer pV2;
  750. // Get initial vertex values.
  751. pV1.SetVertex(pConvObj->m_InpVertex, (*pIndices++));
  752. pV2.SetVertex(pConvObj->m_InpVertex, (*pIndices++));
  753. for (UINT i = PrimitiveCount; i > 1; i -= 2)
  754. {
  755. pV0 = pV1;
  756. pV1 = pV2;
  757. pV2.SetVertex(pConvObj->m_InpVertex, (*pIndices++));
  758. pConvObj->MakeRectPatch(pV0, pV1, pV2);
  759. pV0 = pV1;
  760. pV1 = pV2;
  761. pV2.SetVertex(pConvObj->m_InpVertex, (*pIndices++));
  762. pConvObj->MakeRectPatch(pV0, pV2, pV1);
  763. }
  764. if (i > 0)
  765. {
  766. pV0 = pV1;
  767. pV1 = pV2;
  768. pV2.SetVertex(pConvObj->m_InpVertex, (*pIndices++));
  769. pConvObj->MakeRectPatch(pV0, pV1, pV2);
  770. }
  771. }
  772. break;
  773. case D3DPT_TRIANGLEFAN:
  774. {
  775. CVertexPointer pV1;
  776. CVertexPointer pV2;
  777. pV2.SetVertex(pConvObj->m_InpVertex, (*pIndices++));
  778. // Preload initial pV0.
  779. pV1.SetVertex(pConvObj->m_InpVertex, (*pIndices++));
  780. for (UINT i = PrimitiveCount; i > 0; i--)
  781. {
  782. CVertexPointer pV0 = pV1;
  783. pV1.SetVertex(pConvObj->m_InpVertex, (*pIndices++));
  784. pConvObj->MakeRectPatch(pV0, pV2, pV1);
  785. }
  786. }
  787. break;
  788. default:
  789. DXGASSERT(FALSE);
  790. }
  791. }
  792. DrawPatches(pDevice, PrimitiveCount);
  793. }
  794. //-----------------------------------------------------------------------------
  795. // Conversion output will have the same number of streams as input and the
  796. // same vertex shader
  797. //
  798. void CD3DHal::PrepareNPatchConversion(UINT PrimitiveCount, UINT StartVertex)
  799. {
  800. if (m_pConvObj == NULL)
  801. {
  802. m_pConvObj = new CNPatch2TriPatch;
  803. if (m_pConvObj == NULL)
  804. {
  805. D3D_THROW(E_OUTOFMEMORY, "Not enough memory");
  806. }
  807. // Pre-allocate output streams
  808. for (int i=0; i < __NUMELEMENTS; i++)
  809. {
  810. m_pConvObj->m_pOutStream[i]->Grow(512*32, m_pDDI);
  811. }
  812. }
  813. m_pConvObj->m_PositionOrder = (D3DORDERTYPE)rstates[D3DRS_POSITIONORDER];
  814. m_pConvObj->m_NormalOrder = (D3DORDERTYPE)rstates[D3DRS_NORMALORDER];
  815. m_pConvObj->m_bNormalizeNormals = rstates[D3DRS_NORMALIZENORMALS];
  816. // Compute number of vertices in the output. Each output patch has 16
  817. // control points
  818. UINT nOutVertices = PrimitiveCount * 16;
  819. if (D3DVSD_ISLEGACY(m_dwCurrentShaderHandle))
  820. {
  821. CVStream* pStream = &m_pStream[0];
  822. UINT Stride = pStream->m_dwStride;
  823. // Get memory pointer for the input stream 0
  824. m_pConvObj->m_pInpStreamMem[0] = pStream->Data() + StartVertex * Stride;
  825. if (Stride != m_pConvObj->m_pOutStream[0]->m_dwStride &&
  826. m_pConvObj->m_pOutStream[0]->GetPrimitiveBase() != 0)
  827. {
  828. m_pDDI->FlushStates();
  829. m_pConvObj->m_pOutStream[0]->Reset();
  830. m_pConvObj->m_FirstVertex = 0;
  831. }
  832. // Allocate space in the corresponding output stream and get its
  833. // memory pointer
  834. m_pConvObj->m_pOutStreamMem[0] = m_pConvObj->m_pOutStream[0]->Lock(nOutVertices * Stride, m_pDDI);
  835. m_pConvObj->m_pOutStream[0]->SetVertexSize(Stride);
  836. m_pConvObj->m_FirstVertex = m_pConvObj->m_pOutStream[0]->GetPrimitiveBase();
  837. m_pConvObj->m_FirstVertex /= Stride;
  838. m_pConvObj->m_pOutStream[0]->SkipVertices(nOutVertices);
  839. // Save the old vertex buffer
  840. UINT tmp;
  841. GetStreamSource(0, (IDirect3DVertexBuffer8**)&m_pConvObj->m_InpStream[0].m_pVB, &tmp);
  842. // Set new vertex buffer as input stream
  843. SetStreamSource(0, m_pConvObj->m_pOutStream[0]->m_pVB, Stride);
  844. // Initialize vertex elements pointers based on the FVF handle
  845. UINT VertexOffset = 0;
  846. CVertexPointer::NumUsedElements = 0;
  847. BYTE* pinp = m_pConvObj->m_pInpStreamMem[0];
  848. BYTE* pout = m_pConvObj->m_pOutStreamMem[0];
  849. // Position
  850. m_pConvObj->m_PositionIndex = CVertexPointer::NumUsedElements;
  851. m_pConvObj->m_InpVertex.Stride[CVertexPointer::NumUsedElements] = Stride;
  852. m_pConvObj->m_InpVertex.pData[CVertexPointer::NumUsedElements] = pinp;
  853. m_pConvObj->m_OutVertex.pData[CVertexPointer::NumUsedElements] = pout;
  854. VertexOffset += 3*sizeof(float);
  855. CVertexPointer::DataType[CVertexPointer::NumUsedElements] = D3DVSDT_FLOAT3;
  856. CVertexPointer::NumUsedElements++;
  857. // Data after position
  858. switch (m_dwCurrentShaderHandle & D3DFVF_POSITION_MASK)
  859. {
  860. case D3DFVF_XYZB1:
  861. m_pConvObj->m_InpVertex.Stride[CVertexPointer::NumUsedElements] = Stride;
  862. m_pConvObj->m_InpVertex.pData[CVertexPointer::NumUsedElements] = pinp + VertexOffset;
  863. m_pConvObj->m_OutVertex.pData[CVertexPointer::NumUsedElements] = pout + VertexOffset;
  864. VertexOffset += sizeof(float);
  865. CVertexPointer::DataType[CVertexPointer::NumUsedElements] = D3DVSDT_FLOAT1;
  866. CVertexPointer::NumUsedElements++;
  867. break;
  868. case D3DFVF_XYZB2:
  869. m_pConvObj->m_InpVertex.Stride[CVertexPointer::NumUsedElements] = Stride;
  870. m_pConvObj->m_InpVertex.pData[CVertexPointer::NumUsedElements] = pinp + VertexOffset;
  871. m_pConvObj->m_OutVertex.pData[CVertexPointer::NumUsedElements] = pout + VertexOffset;
  872. VertexOffset += sizeof(float) * 2;
  873. CVertexPointer::DataType[CVertexPointer::NumUsedElements] = D3DVSDT_FLOAT2;
  874. CVertexPointer::NumUsedElements++;
  875. break;
  876. case D3DFVF_XYZB3:
  877. m_pConvObj->m_InpVertex.Stride[CVertexPointer::NumUsedElements] = Stride;
  878. m_pConvObj->m_InpVertex.pData[CVertexPointer::NumUsedElements] = pinp + VertexOffset;
  879. m_pConvObj->m_OutVertex.pData[CVertexPointer::NumUsedElements] = pout + VertexOffset;
  880. VertexOffset += sizeof(float) * 3;
  881. CVertexPointer::DataType[CVertexPointer::NumUsedElements] = D3DVSDT_FLOAT3;
  882. CVertexPointer::NumUsedElements++;
  883. break;
  884. case D3DFVF_XYZB4:
  885. m_pConvObj->m_InpVertex.Stride[CVertexPointer::NumUsedElements] = Stride;
  886. m_pConvObj->m_InpVertex.pData[CVertexPointer::NumUsedElements] = pinp + VertexOffset;
  887. m_pConvObj->m_OutVertex.pData[CVertexPointer::NumUsedElements] = pout + VertexOffset;
  888. VertexOffset += sizeof(float) * 4;
  889. CVertexPointer::DataType[CVertexPointer::NumUsedElements] = D3DVSDT_FLOAT4;
  890. CVertexPointer::NumUsedElements++;
  891. break;
  892. case D3DFVF_XYZB5:
  893. m_pConvObj->m_InpVertex.Stride[CVertexPointer::NumUsedElements] = Stride;
  894. m_pConvObj->m_InpVertex.pData[CVertexPointer::NumUsedElements] = pinp + VertexOffset;
  895. m_pConvObj->m_OutVertex.pData[CVertexPointer::NumUsedElements] = pout + VertexOffset;
  896. VertexOffset += sizeof(float) * 4;
  897. CVertexPointer::DataType[CVertexPointer::NumUsedElements] = D3DVSDT_FLOAT4;
  898. CVertexPointer::NumUsedElements++;
  899. m_pConvObj->m_InpVertex.Stride[CVertexPointer::NumUsedElements] = Stride;
  900. m_pConvObj->m_InpVertex.pData[CVertexPointer::NumUsedElements] = pinp + VertexOffset;
  901. m_pConvObj->m_OutVertex.pData[CVertexPointer::NumUsedElements] = pout + VertexOffset;
  902. VertexOffset += sizeof(float) * 1;
  903. CVertexPointer::DataType[CVertexPointer::NumUsedElements] = D3DVSDT_FLOAT1;
  904. CVertexPointer::NumUsedElements++;
  905. break;
  906. }
  907. //Normal
  908. m_pConvObj->m_NormalIndex = CVertexPointer::NumUsedElements;
  909. m_pConvObj->m_InpVertex.Stride[CVertexPointer::NumUsedElements] = Stride;
  910. m_pConvObj->m_InpVertex.pData[CVertexPointer::NumUsedElements] = pinp + VertexOffset;
  911. m_pConvObj->m_OutVertex.pData[CVertexPointer::NumUsedElements] = pout + VertexOffset;
  912. VertexOffset += 3*sizeof(float);
  913. CVertexPointer::DataType[CVertexPointer::NumUsedElements] = D3DVSDT_FLOAT3;
  914. CVertexPointer::NumUsedElements++;
  915. if (m_dwCurrentShaderHandle & D3DFVF_PSIZE)
  916. {
  917. m_pConvObj->m_InpVertex.Stride[CVertexPointer::NumUsedElements] = Stride;
  918. m_pConvObj->m_InpVertex.pData[CVertexPointer::NumUsedElements] = pinp + VertexOffset;
  919. m_pConvObj->m_OutVertex.pData[CVertexPointer::NumUsedElements] = pout + VertexOffset;
  920. VertexOffset += sizeof(float);
  921. CVertexPointer::DataType[CVertexPointer::NumUsedElements] = D3DVSDT_FLOAT1;
  922. CVertexPointer::NumUsedElements++;
  923. }
  924. if (m_dwCurrentShaderHandle & D3DFVF_DIFFUSE)
  925. {
  926. m_pConvObj->m_InpVertex.Stride[CVertexPointer::NumUsedElements] = Stride;
  927. m_pConvObj->m_InpVertex.pData[CVertexPointer::NumUsedElements] = pinp + VertexOffset;
  928. m_pConvObj->m_OutVertex.pData[CVertexPointer::NumUsedElements] = pout + VertexOffset;
  929. VertexOffset += sizeof(DWORD);
  930. CVertexPointer::DataType[CVertexPointer::NumUsedElements] = D3DVSDT_D3DCOLOR;
  931. CVertexPointer::NumUsedElements++;
  932. }
  933. if (m_dwCurrentShaderHandle & D3DFVF_SPECULAR)
  934. {
  935. m_pConvObj->m_InpVertex.Stride[CVertexPointer::NumUsedElements] = Stride;
  936. m_pConvObj->m_InpVertex.pData[CVertexPointer::NumUsedElements] = pinp + VertexOffset;
  937. m_pConvObj->m_OutVertex.pData[CVertexPointer::NumUsedElements] = pout + VertexOffset;
  938. VertexOffset += sizeof(DWORD);
  939. CVertexPointer::DataType[CVertexPointer::NumUsedElements] = D3DVSDT_D3DCOLOR;
  940. CVertexPointer::NumUsedElements++;
  941. }
  942. UINT iTexCount = FVF_TEXCOORD_NUMBER(m_dwCurrentShaderHandle);
  943. for (UINT i = 0; i < iTexCount; i++)
  944. {
  945. switch (D3DFVF_GETTEXCOORDSIZE(m_dwCurrentShaderHandle, i))
  946. {
  947. case D3DFVF_TEXTUREFORMAT2:
  948. m_pConvObj->m_InpVertex.Stride[CVertexPointer::NumUsedElements] = Stride;
  949. m_pConvObj->m_InpVertex.pData[CVertexPointer::NumUsedElements] = pinp + VertexOffset;
  950. m_pConvObj->m_OutVertex.pData[CVertexPointer::NumUsedElements] = pout + VertexOffset;
  951. VertexOffset += sizeof(float) * 2;
  952. CVertexPointer::DataType[CVertexPointer::NumUsedElements] = D3DVSDT_FLOAT2;
  953. CVertexPointer::NumUsedElements++;
  954. break;
  955. case D3DFVF_TEXTUREFORMAT1:
  956. m_pConvObj->m_InpVertex.Stride[CVertexPointer::NumUsedElements] = Stride;
  957. m_pConvObj->m_InpVertex.pData[CVertexPointer::NumUsedElements] = pinp + VertexOffset;
  958. m_pConvObj->m_OutVertex.pData[CVertexPointer::NumUsedElements] = pout + VertexOffset;
  959. VertexOffset += sizeof(float);
  960. CVertexPointer::DataType[CVertexPointer::NumUsedElements] = D3DVSDT_FLOAT1;
  961. CVertexPointer::NumUsedElements++;
  962. break;
  963. case D3DFVF_TEXTUREFORMAT3:
  964. m_pConvObj->m_InpVertex.Stride[CVertexPointer::NumUsedElements] = Stride;
  965. m_pConvObj->m_InpVertex.pData[CVertexPointer::NumUsedElements] = pinp + VertexOffset;
  966. m_pConvObj->m_OutVertex.pData[CVertexPointer::NumUsedElements] = pout + VertexOffset;
  967. VertexOffset += sizeof(float) * 3;
  968. CVertexPointer::DataType[CVertexPointer::NumUsedElements] = D3DVSDT_FLOAT3;
  969. CVertexPointer::NumUsedElements++;
  970. break;
  971. case D3DFVF_TEXTUREFORMAT4:
  972. m_pConvObj->m_InpVertex.Stride[CVertexPointer::NumUsedElements] = Stride;
  973. m_pConvObj->m_InpVertex.pData[CVertexPointer::NumUsedElements] = pinp + VertexOffset;
  974. m_pConvObj->m_OutVertex.pData[CVertexPointer::NumUsedElements] = pout + VertexOffset;
  975. VertexOffset += sizeof(float) * 4;
  976. CVertexPointer::DataType[CVertexPointer::NumUsedElements] = D3DVSDT_FLOAT4;
  977. CVertexPointer::NumUsedElements++;
  978. break;
  979. }
  980. }
  981. }
  982. else
  983. {
  984. // Check if we can batch to the same output vertex streams.
  985. // All output streams must have the same stride as declaration, the
  986. // same primitive base and enough space to store output vertices
  987. CVStreamDecl* pStreamDecl = m_pCurrentShader->m_Declaration.m_pActiveStreams;
  988. BOOL bFirstStream = TRUE;
  989. UINT FirstVertexIndex = 0;
  990. while (pStreamDecl)
  991. {
  992. UINT si = pStreamDecl->m_dwStreamIndex;
  993. UINT Stride = pStreamDecl->m_dwStride;
  994. UINT PrimitiveBase = m_pConvObj->m_pOutStream[si]->GetPrimitiveBase();
  995. PrimitiveBase /= Stride;
  996. if (bFirstStream)
  997. {
  998. FirstVertexIndex = PrimitiveBase;
  999. m_pConvObj->m_FirstVertex = FirstVertexIndex;
  1000. }
  1001. if ((m_pConvObj->m_pOutStream[si]->m_dwStride != Stride &&
  1002. PrimitiveBase != 0) || FirstVertexIndex != PrimitiveBase ||
  1003. !m_pConvObj->m_pOutStream[si]->CheckFreeSpace(nOutVertices * Stride))
  1004. {
  1005. m_pDDI->FlushStates();
  1006. for (int i=0; i < __NUMELEMENTS; i++)
  1007. {
  1008. m_pConvObj->m_pOutStream[i]->Reset();
  1009. }
  1010. m_pConvObj->m_FirstVertex = 0;
  1011. }
  1012. bFirstStream = FALSE;
  1013. pStreamDecl = (CVStreamDecl*)pStreamDecl->m_pNext;
  1014. }
  1015. // Build an array of all vertex elements used in the shader by going
  1016. // through all streams and elements inside each stream.
  1017. CVDeclaration* pDecl = &m_pCurrentShader->m_Declaration;
  1018. pStreamDecl = m_pCurrentShader->m_Declaration.m_pActiveStreams;
  1019. UINT ve = 0; // Vertex element index
  1020. bFirstStream = TRUE;
  1021. while (pStreamDecl)
  1022. {
  1023. UINT si = pStreamDecl->m_dwStreamIndex;
  1024. UINT Stride = pStreamDecl->m_dwStride;
  1025. CVStream * pStream = &m_pStream[si];
  1026. m_pConvObj->m_pInpStreamMem[si] = pStream->Data() + StartVertex * Stride;
  1027. // Allocate space in the corresponding output stream and get
  1028. // memory pointer
  1029. m_pConvObj->m_pOutStreamMem[si] = m_pConvObj->m_pOutStream[si]->Lock(nOutVertices * Stride, m_pDDI);
  1030. m_pConvObj->m_pOutStream[si]->SetVertexSize(Stride);
  1031. m_pConvObj->m_pOutStream[si]->SkipVertices(nOutVertices);
  1032. // Save the old vertex buffer
  1033. UINT tmp;
  1034. GetStreamSource(si, (IDirect3DVertexBuffer8**)&m_pConvObj->m_InpStream[si].m_pVB, &tmp);
  1035. // Set new vertex buffer as input
  1036. SetStreamSource(si, m_pConvObj->m_pOutStream[si]->m_pVB, Stride);
  1037. for (DWORD i=0; i < pStreamDecl->m_dwNumElements; i++)
  1038. {
  1039. if (i >= __NUMELEMENTS)
  1040. {
  1041. D3D_THROW_FAIL("Declaration is using too many elements");
  1042. }
  1043. // This is the array we build
  1044. CVElement* pVerElem = &pStreamDecl->m_Elements[i];
  1045. CVertexPointer::Stride[ve] = Stride;
  1046. CVertexPointer::DataType[ve] = pVerElem->m_dwDataType;
  1047. m_pConvObj->m_InpVertex.pData[ve] = m_pConvObj->m_pInpStreamMem[si] + pVerElem->m_dwOffset;
  1048. m_pConvObj->m_OutVertex.pData[ve] = m_pConvObj->m_pOutStreamMem[si] + pVerElem->m_dwOffset;
  1049. if (pVerElem->m_dwRegister == D3DVSDE_POSITION)
  1050. m_pConvObj->m_PositionIndex = ve;
  1051. else
  1052. if (pVerElem->m_dwRegister == D3DVSDE_NORMAL)
  1053. m_pConvObj->m_NormalIndex = ve;
  1054. ve++;
  1055. }
  1056. pStreamDecl = (CVStreamDecl*)pStreamDecl->m_pNext;
  1057. }
  1058. pDecl->m_dwNumElements = ve;
  1059. CVertexPointer::NumUsedElements = ve;
  1060. }
  1061. }