Leaked source code of windows server 2003
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.

401 lines
16 KiB

  1. /*==========================================================================;
  2. *
  3. * Copyright (C) 1997 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: helxfrm.c
  6. * Content: Direct3D front-end transform and process vertices
  7. *
  8. ***************************************************************************/
  9. #include "pch.cpp"
  10. #pragma hdrstop
  11. #include "light.h"
  12. void MatrixProduct2(D3DMATRIXI *result, D3DMATRIXI *a, D3DMATRIXI *b);
  13. D3DFE_PVFUNCS GeometryFuncsGuaranteed; // Our implementation
  14. //---------------------------------------------------------------------
  15. void CheckWorldViewMatrix(LPD3DFE_PROCESSVERTICES pv)
  16. {
  17. D3DMATRIXI *m = &pv->mWV;
  18. D3DMATRIXI res;
  19. res._11 = m->_11*m->_11 + m->_12*m->_12 + m->_13*m->_13;
  20. res._12 = m->_11*m->_21 + m->_12*m->_22 + m->_13*m->_23;
  21. res._13 = m->_11*m->_31 + m->_12*m->_32 + m->_13*m->_33;
  22. res._21 = m->_21*m->_11 + m->_22*m->_12 + m->_23*m->_13;
  23. res._22 = m->_21*m->_21 + m->_22*m->_22 + m->_23*m->_23;
  24. res._23 = m->_21*m->_31 + m->_22*m->_32 + m->_23*m->_33;
  25. res._31 = m->_31*m->_11 + m->_32*m->_12 + m->_33*m->_13;
  26. res._32 = m->_31*m->_21 + m->_32*m->_22 + m->_33*m->_23;
  27. res._33 = m->_31*m->_31 + m->_32*m->_32 + m->_33*m->_33;
  28. const D3DVALUE eps = 0.0001f;
  29. if (m->_14 == 0.0f &&
  30. m->_24 == 0.0f &&
  31. m->_34 == 0.0f &&
  32. m->_44 == 1.0f &&
  33. ABSF(res._12) < eps &&
  34. ABSF(res._13) < eps &&
  35. ABSF(res._21) < eps &&
  36. ABSF(res._23) < eps &&
  37. ABSF(res._31) < eps &&
  38. ABSF(res._32) < eps &&
  39. ABSF(1.0f - res._11) < eps &&
  40. ABSF(1.0f - res._22) < eps &&
  41. ABSF(1.0f - res._33) < eps)
  42. {
  43. pv->dwDeviceFlags |= D3DDEV_MODELSPACELIGHTING;
  44. }
  45. else
  46. {
  47. pv->dwDeviceFlags &= ~D3DDEV_MODELSPACELIGHTING;
  48. }
  49. }
  50. //---------------------------------------------------------------------
  51. void setIdentity(D3DMATRIXI * m)
  52. {
  53. m->_11 = D3DVAL(1.0); m->_12 = D3DVAL(0.0); m->_13 = D3DVAL(0.0); m->_14 = D3DVAL(0.0);
  54. m->_21 = D3DVAL(0.0); m->_22 = D3DVAL(1.0); m->_23 = D3DVAL(0.0); m->_24 = D3DVAL(0.0);
  55. m->_31 = D3DVAL(0.0); m->_32 = D3DVAL(0.0); m->_33 = D3DVAL(1.0); m->_34 = D3DVAL(0.0);
  56. m->_41 = D3DVAL(0.0); m->_42 = D3DVAL(0.0); m->_43 = D3DVAL(0.0); m->_44 = D3DVAL(1.0);
  57. }
  58. //---------------------------------------------------------------------
  59. /*
  60. * Combine all matrices.
  61. */
  62. const DWORD __VPC_DIRTY = D3DFE_VIEWMATRIX_DIRTY |
  63. D3DFE_PROJMATRIX_DIRTY;
  64. void updateTransform(LPDIRECT3DDEVICEI lpDevI)
  65. {
  66. D3DFE_VIEWPORTCACHE& VPORT = lpDevI->vcache;
  67. D3DFE_TRANSFORM& TRANSFORM = lpDevI->transform;
  68. if (lpDevI->dwFEFlags & D3DFE_PROJMATRIX_DIRTY)
  69. {
  70. // We modify the projection matrix to make the clipping rules to be
  71. // 0 < x,y,z < w
  72. TRANSFORM.mPC._11 = (TRANSFORM.proj._11 + TRANSFORM.proj._14) * D3DVAL(0.5);
  73. TRANSFORM.mPC._12 = (TRANSFORM.proj._12 + TRANSFORM.proj._14) * D3DVAL(0.5);
  74. TRANSFORM.mPC._13 = TRANSFORM.proj._13;
  75. TRANSFORM.mPC._14 = TRANSFORM.proj._14;
  76. TRANSFORM.mPC._21 = (TRANSFORM.proj._21 + TRANSFORM.proj._24) * D3DVAL(0.5);
  77. TRANSFORM.mPC._22 = (TRANSFORM.proj._22 + TRANSFORM.proj._24) * D3DVAL(0.5);
  78. TRANSFORM.mPC._23 = TRANSFORM.proj._23;
  79. TRANSFORM.mPC._24 = TRANSFORM.proj._24;
  80. TRANSFORM.mPC._31 = (TRANSFORM.proj._31 + TRANSFORM.proj._34) * D3DVAL(0.5);
  81. TRANSFORM.mPC._32 = (TRANSFORM.proj._32 + TRANSFORM.proj._34) * D3DVAL(0.5);
  82. TRANSFORM.mPC._33 = TRANSFORM.proj._33;
  83. TRANSFORM.mPC._34 = TRANSFORM.proj._34;
  84. TRANSFORM.mPC._41 = (TRANSFORM.proj._41 + TRANSFORM.proj._44) * D3DVAL(0.5);
  85. TRANSFORM.mPC._42 = (TRANSFORM.proj._42 + TRANSFORM.proj._44) * D3DVAL(0.5);
  86. TRANSFORM.mPC._43 = TRANSFORM.proj._43;
  87. TRANSFORM.mPC._44 = TRANSFORM.proj._44;
  88. }
  89. if (lpDevI->dwFEFlags & (D3DFE_VIEWMATRIX_DIRTY |
  90. D3DFE_PROJMATRIX_DIRTY))
  91. { // Update Mview*Mproj*Mclip
  92. MatrixProduct(&TRANSFORM.mVPC, &TRANSFORM.view, &TRANSFORM.mPC);
  93. lpDevI->dwFEFlags |= D3DFE_CLIPMATRIX_DIRTY | D3DFE_CLIPPLANES_DIRTY;
  94. }
  95. MatrixProduct(&lpDevI->mCTM, &TRANSFORM.world[0], &TRANSFORM.mVPC);
  96. // Set dirty bit for world*view matrix (needed for fog and lighting)
  97. if (lpDevI->dwFEFlags & (D3DFE_VIEWMATRIX_DIRTY |
  98. D3DFE_WORLDMATRIX_DIRTY |
  99. D3DFE_WORLDMATRIX1_DIRTY |
  100. D3DFE_WORLDMATRIX2_DIRTY |
  101. D3DFE_WORLDMATRIX3_DIRTY))
  102. {
  103. lpDevI->dwFEFlags |= D3DFE_WORLDVIEWMATRIX_DIRTY |
  104. D3DFE_INVWORLDVIEWMATRIX_DIRTY |
  105. D3DFE_NEEDCHECKWORLDVIEWVMATRIX;
  106. }
  107. if (lpDevI->dwFEFlags & (__VPC_DIRTY |
  108. D3DFE_WORLDMATRIX1_DIRTY |
  109. D3DFE_WORLDMATRIX2_DIRTY |
  110. D3DFE_WORLDMATRIX3_DIRTY))
  111. {
  112. if (lpDevI->dwFEFlags & (__VPC_DIRTY | D3DFE_WORLDMATRIX1_DIRTY))
  113. {
  114. MatrixProduct(&lpDevI->mCTM2[0], &TRANSFORM.world[1], &TRANSFORM.mVPC);
  115. }
  116. if (lpDevI->dwFEFlags & (__VPC_DIRTY | D3DFE_WORLDMATRIX2_DIRTY))
  117. {
  118. MatrixProduct(&lpDevI->mCTM2[1], &TRANSFORM.world[2], &TRANSFORM.mVPC);
  119. }
  120. if (lpDevI->dwFEFlags & (__VPC_DIRTY | D3DFE_WORLDMATRIX3_DIRTY))
  121. {
  122. MatrixProduct(&lpDevI->mCTM2[2], &TRANSFORM.world[3], &TRANSFORM.mVPC);
  123. }
  124. }
  125. // All matrices are set up
  126. lpDevI->dwFEFlags &= ~D3DFE_TRANSFORM_DIRTY;
  127. // Set dirty bit for lighting
  128. lpDevI->dwFEFlags |= D3DFE_NEED_TRANSFORM_LIGHTS |
  129. D3DFE_FRUSTUMPLANES_DIRTY;
  130. lpDevI->dwDeviceFlags |= D3DDEV_TRANSFORMDIRTY;
  131. }
  132. //---------------------------------------------------------------------
  133. #define MATRIX_PRODUCT(res, a, b) \
  134. res->_11 = a->_11*b->_11 + a->_12*b->_21 + a->_13*b->_31 + a->_14*b->_41; \
  135. res->_12 = a->_11*b->_12 + a->_12*b->_22 + a->_13*b->_32 + a->_14*b->_42; \
  136. res->_13 = a->_11*b->_13 + a->_12*b->_23 + a->_13*b->_33 + a->_14*b->_43; \
  137. res->_14 = a->_11*b->_14 + a->_12*b->_24 + a->_13*b->_34 + a->_14*b->_44; \
  138. \
  139. res->_21 = a->_21*b->_11 + a->_22*b->_21 + a->_23*b->_31 + a->_24*b->_41; \
  140. res->_22 = a->_21*b->_12 + a->_22*b->_22 + a->_23*b->_32 + a->_24*b->_42; \
  141. res->_23 = a->_21*b->_13 + a->_22*b->_23 + a->_23*b->_33 + a->_24*b->_43; \
  142. res->_24 = a->_21*b->_14 + a->_22*b->_24 + a->_23*b->_34 + a->_24*b->_44; \
  143. \
  144. res->_31 = a->_31*b->_11 + a->_32*b->_21 + a->_33*b->_31 + a->_34*b->_41; \
  145. res->_32 = a->_31*b->_12 + a->_32*b->_22 + a->_33*b->_32 + a->_34*b->_42; \
  146. res->_33 = a->_31*b->_13 + a->_32*b->_23 + a->_33*b->_33 + a->_34*b->_43; \
  147. res->_34 = a->_31*b->_14 + a->_32*b->_24 + a->_33*b->_34 + a->_34*b->_44; \
  148. \
  149. res->_41 = a->_41*b->_11 + a->_42*b->_21 + a->_43*b->_31 + a->_44*b->_41; \
  150. res->_42 = a->_41*b->_12 + a->_42*b->_22 + a->_43*b->_32 + a->_44*b->_42; \
  151. res->_43 = a->_41*b->_13 + a->_42*b->_23 + a->_43*b->_33 + a->_44*b->_43; \
  152. res->_44 = a->_41*b->_14 + a->_42*b->_24 + a->_43*b->_34 + a->_44*b->_44;
  153. //---------------------------------------------------------------------
  154. // result = a*b.
  155. // "result" pointer could be equal to "a" or "b"
  156. //
  157. void MatrixProduct(D3DMATRIXI *result, D3DMATRIXI *a, D3DMATRIXI *b)
  158. {
  159. if (result == a || result == b)
  160. {
  161. MatrixProduct2(result, a, b);
  162. return;
  163. }
  164. MATRIX_PRODUCT(result, a, b);
  165. }
  166. //---------------------------------------------------------------------
  167. // result = a*b
  168. // result is the same as a or b
  169. //
  170. void MatrixProduct2(D3DMATRIXI *result, D3DMATRIXI *a, D3DMATRIXI *b)
  171. {
  172. D3DMATRIX res;
  173. MATRIX_PRODUCT((&res), a, b);
  174. *(D3DMATRIX*)result = res;
  175. }
  176. //----------------------------------------------------------------------------
  177. #ifdef DEBUG_PIPELINE
  178. extern DWORD g_DebugFlags;
  179. #endif
  180. //
  181. // DoUpdateState should be called for every DrawPrimitive call in the slow path,
  182. // because it sets some internal pipeline flags. These flags are persistent for the
  183. // fast path
  184. //
  185. void DoUpdateState(LPDIRECT3DDEVICEI lpDevI)
  186. {
  187. // only set up lights if something has changed
  188. if (lpDevI->dwFEFlags & D3DFE_LIGHTS_DIRTY)
  189. {
  190. LPDIRECT3DLIGHTI lpD3DLightI;
  191. lpD3DLightI = (LPDIRECT3DLIGHTI)LIST_FIRST(&lpDevI->m_ActiveLights);
  192. lpDevI->lighting.activeLights = NULL;
  193. // Set lights in the device
  194. while (lpD3DLightI)
  195. {
  196. if (lpD3DLightI->m_LightI.flags & D3DLIGHTI_DIRTY)
  197. lpD3DLightI->SetInternalData();
  198. lpD3DLightI->m_LightI.next = lpDevI->lighting.activeLights;
  199. lpDevI->lighting.activeLights = &lpD3DLightI->m_LightI;
  200. lpD3DLightI = (LPDIRECT3DLIGHTI)LIST_NEXT(lpD3DLightI, m_List);
  201. }
  202. }
  203. if (lpDevI->dwDeviceFlags & D3DDEV_LIGHTING &&
  204. lpDevI->dwVIDOut & (D3DFVF_DIFFUSE | D3DFVF_SPECULAR))
  205. {
  206. lpDevI->dwFlags |= D3DPV_LIGHTING;
  207. }
  208. if (lpDevI->dwDeviceFlags & D3DDEV_FOG && lpDevI->dwVIDOut & D3DFVF_SPECULAR)
  209. {
  210. lpDevI->dwFlags |= D3DPV_FOG;
  211. }
  212. if (lpDevI->dwFEFlags & D3DFE_VERTEXBLEND_DIRTY)
  213. {
  214. lpDevI->dwNumVerBlends = min(lpDevI->rstates[D3DRENDERSTATE_VERTEXBLEND],
  215. ((lpDevI->dwVIDIn & D3DFVF_POSITION_MASK) >> 1) - 2);
  216. lpDevI->dwFEFlags &= ~D3DFE_VERTEXBLEND_DIRTY;
  217. // Lighting is done in the camera space when there is vertex blending
  218. if (lpDevI->dwNumVerBlends)
  219. {
  220. if (lpDevI->dwDeviceFlags & D3DDEV_MODELSPACELIGHTING)
  221. {
  222. lpDevI->dwDeviceFlags &= ~(D3DDEV_MODELSPACELIGHTING | D3DFE_NEEDCHECKWORLDVIEWVMATRIX);
  223. // We have to transform lights to the camera space
  224. lpDevI->dwFEFlags |= D3DFE_NEED_TRANSFORM_LIGHTS;
  225. }
  226. }
  227. else
  228. {
  229. if (!(lpDevI->dwDeviceFlags & D3DDEV_MODELSPACELIGHTING))
  230. lpDevI->dwFEFlags |= D3DFE_NEEDCHECKWORLDVIEWVMATRIX;
  231. }
  232. }
  233. if (lpDevI->dwFEFlags & D3DFE_TRANSFORM_DIRTY)
  234. {
  235. updateTransform(lpDevI);
  236. }
  237. // We need World-View matrix for lighting, fog and when texture coordinates
  238. // are taken from the vertex data in the camera space
  239. if (lpDevI->dwFEFlags & D3DFE_WORLDVIEWMATRIX_DIRTY &&
  240. (lpDevI->dwFlags & (D3DPV_LIGHTING | D3DPV_FOG) ||
  241. lpDevI->dwDeviceFlags & (D3DDEV_NORMALINCAMERASPACE | D3DDEV_POSITIONINCAMERASPACE)))
  242. {
  243. MatrixProduct(&lpDevI->mWV, &lpDevI->transform.world[0],
  244. &lpDevI->transform.view);
  245. for (DWORD i=0; i < lpDevI->dwNumVerBlends; i++)
  246. {
  247. MatrixProduct(&lpDevI->mWV2[i], &lpDevI->transform.world[i+1],
  248. &lpDevI->transform.view);
  249. }
  250. lpDevI->dwFEFlags &= ~D3DFE_WORLDVIEWMATRIX_DIRTY;
  251. }
  252. // Detect where to do lighting: in model or eye space
  253. if (lpDevI->dwFEFlags & D3DFE_NEEDCHECKWORLDVIEWVMATRIX &&
  254. lpDevI->dwFlags & D3DPV_LIGHTING)
  255. {
  256. // We try to do lighting in the model space if
  257. // 1. we do not have to normalize normals
  258. // 2. we do not need to do vertex blending
  259. lpDevI->dwDeviceFlags &= ~D3DDEV_MODELSPACELIGHTING;
  260. if (lpDevI->dwNumVerBlends == 0 &&
  261. !(lpDevI->dwDeviceFlags & D3DDEV_NORMALIZENORMALS))
  262. {
  263. #ifdef DEBUG_PIPELINE
  264. if (!(g_DebugFlags & __DEBUG_MODELSPACE))
  265. #endif
  266. {
  267. CheckWorldViewMatrix(lpDevI);
  268. lpDevI->dwFEFlags &= ~D3DFE_NEEDCHECKWORLDVIEWVMATRIX;
  269. }
  270. }
  271. // If D3DDEV_MODELSPACELIGHTING has been changed we need to re-transform lights
  272. lpDevI->dwFEFlags |= D3DFE_NEED_TRANSFORM_LIGHTS;
  273. }
  274. // Updating inverse World-View matrix
  275. if (lpDevI->dwFEFlags & D3DFE_INVWORLDVIEWMATRIX_DIRTY &&
  276. ((lpDevI->dwFlags & D3DPV_LIGHTING && !(lpDevI->dwDeviceFlags & D3DDEV_MODELSPACELIGHTING)) ||
  277. lpDevI->dwDeviceFlags & D3DDEV_NORMALINCAMERASPACE))
  278. {
  279. Inverse4x4((D3DMATRIX*)&lpDevI->mWV, (D3DMATRIX*)&lpDevI->mWVI);
  280. for (DWORD i=0; i < lpDevI->dwNumVerBlends; i++)
  281. {
  282. Inverse4x4((D3DMATRIX*)&lpDevI->mWV2[i], (D3DMATRIX*)&lpDevI->mWVI2[i]);
  283. }
  284. lpDevI->dwFEFlags &= ~D3DFE_INVWORLDVIEWMATRIX_DIRTY;
  285. }
  286. // Update clipping planes if there are any
  287. if (lpDevI->dwFEFlags & D3DFE_CLIPPLANES_DIRTY)
  288. {
  289. if (lpDevI->dwFEFlags & D3DFE_CLIPMATRIX_DIRTY)
  290. {
  291. // View and projection matrix are inversed separately, because it
  292. // is possible that combined matrix cannot be inverted. This could happend
  293. // when the view matrix has huge _43 value (> 10^7). Floating point precision
  294. // is not enough in this case
  295. D3DMATRIXI mPCInverse;
  296. if (Inverse4x4((D3DMATRIX*)&lpDevI->transform.mPC, (D3DMATRIX*)&mPCInverse))
  297. {
  298. D3D_ERR("Cannot invert projection matrix");
  299. setIdentity((D3DMATRIXI*)&mPCInverse);
  300. }
  301. D3DMATRIXI mViewInverse;
  302. if (Inverse4x4((D3DMATRIX*)&lpDevI->transform.view, (D3DMATRIX*)&mViewInverse))
  303. {
  304. D3D_ERR("Cannot invert view matrix");
  305. setIdentity((D3DMATRIXI*)&mViewInverse);
  306. }
  307. MatrixProduct(&lpDevI->transform.mVPCI, &mPCInverse, &mViewInverse);
  308. lpDevI->dwFEFlags &= ~D3DFE_CLIPMATRIX_DIRTY;
  309. }
  310. DWORD dwMaxUserClipPlanes = 0;
  311. DWORD dwPlanes = lpDevI->rstates[D3DRENDERSTATE_CLIPPLANEENABLE];
  312. for (DWORD i=0; i < __MAXUSERCLIPPLANES; i++)
  313. {
  314. if (dwPlanes & (1 << i))
  315. {
  316. VecMatMul4HT(&lpDevI->transform.userClipPlane[i],
  317. (D3DMATRIX*)&lpDevI->transform.mVPCI,
  318. &lpDevI->userClipPlane[dwMaxUserClipPlanes]);
  319. dwMaxUserClipPlanes++;
  320. }
  321. }
  322. lpDevI->dwMaxUserClipPlanes = dwMaxUserClipPlanes;
  323. lpDevI->dwFEFlags &= ~D3DFE_CLIPPLANES_DIRTY;
  324. }
  325. if (lpDevI->dwFEFlags & (D3DFE_NEED_TRANSFORM_LIGHTS |
  326. D3DFE_LIGHTS_DIRTY |
  327. D3DFE_MATERIAL_DIRTY))
  328. {
  329. D3DFE_UpdateLights(lpDevI);
  330. // Set a flag for PSGP
  331. lpDevI->dwDeviceFlags |= D3DDEV_LIGHTSDIRTY;
  332. }
  333. // In case if COLORVERTEX is TRUE, the vertexAlpha could be overriden
  334. // by vertex alpha
  335. lpDevI->lighting.alpha = (DWORD)lpDevI->lighting.materialAlpha;
  336. lpDevI->lighting.alphaSpecular = (DWORD)lpDevI->lighting.materialAlphaS;
  337. if (!(lpDevI->dwVIDOut & D3DFVF_DIFFUSE))
  338. lpDevI->dwFlags |= D3DPV_DONOTCOPYDIFFUSE;
  339. if (!(lpDevI->dwVIDOut & D3DFVF_SPECULAR))
  340. lpDevI->dwFlags |= D3DPV_DONOTCOPYSPECULAR;
  341. // This is a hint that only the inPosition pointer needs to be updated
  342. // for speed reasons.
  343. if (((lpDevI->dwVIDIn & ( D3DFVF_DIFFUSE | D3DFVF_SPECULAR | D3DFVF_NORMAL)) == 0) &&
  344. (lpDevI->nTexCoord == 0))
  345. lpDevI->dwFlags |= D3DPV_TRANSFORMONLY;
  346. if (lpDevI->nOutTexCoord == 0)
  347. lpDevI->dwFlags |= D3DPV_DONOTCOPYTEXTURE;
  348. SetInterpolationFlags(lpDevI);
  349. lpDevI->dwFEFlags &= ~D3DFE_FRONTEND_DIRTY;
  350. }
  351. //---------------------------------------------------------------------
  352. // Convert extents from floating point to integer.
  353. //
  354. #undef DPF_MODNAME
  355. #define DPF_MODNAME "D3DFE_ConvertExtent"
  356. void D3DFE_ConvertExtent(LPDIRECT3DDEVICEI lpDevI, LPD3DRECTV from, LPD3DRECT to)
  357. {
  358. to->x1 = FTOI(from->x1) - 1;
  359. to->y1 = FTOI(from->y1) - 1;
  360. to->x2 = FTOI(from->x2) + 1;
  361. to->y2 = FTOI(from->y2) + 1;
  362. if (to->x1 < lpDevI->vcache.minXi)
  363. to->x1 = lpDevI->vcache.minXi;
  364. if (to->y1 < lpDevI->vcache.minYi)
  365. to->y1 = lpDevI->vcache.minYi;
  366. if (to->x2 > lpDevI->vcache.maxXi)
  367. to->x2 = lpDevI->vcache.maxXi;
  368. if (to->y2 > lpDevI->vcache.maxYi)
  369. to->y2 = lpDevI->vcache.maxYi;
  370. }