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.

1290 lines
47 KiB

  1. #include "pch.cpp"
  2. #pragma hdrstop
  3. //---------------------------------------------------------------------
  4. // Constructor:
  5. //
  6. //---------------------------------------------------------------------
  7. RefVP::RefVP() :
  8. m_LightArray(),
  9. m_LightVertexTable()
  10. {
  11. m_LightArray.SetGrowSize( 32 );
  12. memset( &m_Material, 0, sizeof(m_Material) );
  13. memset( &m_xfmProj, 0, sizeof(m_xfmProj) );
  14. memset( &m_xfmView, 0, sizeof(m_xfmView) );
  15. memset( m_xfmWorld, 0, sizeof(m_xfmView)*RD_MAX_WORLD_MATRICES );
  16. m_dwTLState = 0;
  17. m_dwDirtyFlags = 0;
  18. memset( m_xfmCurrent, 0, sizeof(m_xfmView)*RD_MAX_WORLD_MATRICES );
  19. memset( m_xfmToEye, 0, sizeof(m_xfmView)*RD_MAX_WORLD_MATRICES );
  20. memset( m_xfmToEyeInv, 0, sizeof(m_xfmView)*RD_MAX_WORLD_MATRICES );
  21. m_qwFVFIn = 0;
  22. m_numVertexBlends = 0;
  23. memset( &m_TransformData, 0, sizeof(m_TransformData) ) ;
  24. m_fPointSize = 0;
  25. m_fPointAttA = 0;
  26. m_fPointAttB = 0;
  27. m_fPointAttC = 0;
  28. m_fPointSizeMin = 0;
  29. m_fPointSizeMax = RD_MAX_POINT_SIZE;
  30. m_fTweenFactor = 0.0f;
  31. m_LightVertexTable.pfnDirectional = RDLV_Directional;
  32. m_LightVertexTable.pfnParallelPoint = RDLV_Directional;
  33. m_LightVertexTable.pfnSpot = RDLV_PointAndSpot;
  34. m_LightVertexTable.pfnPoint = RDLV_PointAndSpot;
  35. m_dwNumActiveTextureStages = 0;
  36. m_pDev = NULL;
  37. }
  38. //---------------------------------------------------------------------
  39. // SetupStrides:
  40. //---------------------------------------------------------------------
  41. HRESULT
  42. RefDev::SetupStrides()
  43. {
  44. RDVDeclaration& Decl = m_pCurrentVShader->m_Declaration;
  45. // Null out the PtrStrides
  46. m_RefVP.m_position.Null();
  47. m_RefVP.m_position2.Null();
  48. m_RefVP.m_blendweights.Null();
  49. m_RefVP.m_blendindices.Null();
  50. m_RefVP.m_normal.Null();
  51. m_RefVP.m_normal2.Null();
  52. m_RefVP.m_specular.Null();
  53. m_RefVP.m_diffuse.Null();
  54. m_RefVP.m_pointsize.Null();
  55. for( int t = 0; t < 8 ; t++ )
  56. m_RefVP.m_tex[t].Null();
  57. for( DWORD i = 0; i < Decl.m_dwNumElements; i++ )
  58. {
  59. RDVElement& Element = Decl.m_VertexElements[i];
  60. RDVStream& Stream = m_VStream[Element.m_dwStreamIndex];
  61. DWORD dwStride = Stream.m_dwStride;
  62. DWORD dwStartVertex = m_dwStartVertex;
  63. switch( Element.m_dwRegister )
  64. {
  65. case D3DVSDE_POSITION:
  66. m_RefVP.m_position.Init(
  67. (LPBYTE)Stream.m_pData + Element.m_dwOffset +
  68. dwStride * dwStartVertex, dwStride );
  69. break;
  70. case D3DVSDE_POSITION2:
  71. m_RefVP.m_position2.Init(
  72. (LPBYTE)Stream.m_pData + Element.m_dwOffset +
  73. dwStride * dwStartVertex, dwStride );
  74. break;
  75. case D3DVSDE_BLENDWEIGHT:
  76. m_RefVP.m_blendweights.Init(
  77. (LPBYTE)Stream.m_pData + Element.m_dwOffset +
  78. dwStride * dwStartVertex, dwStride );
  79. break;
  80. case D3DVSDE_BLENDINDICES:
  81. // This only happens if the vertex declaration is a non-FVF one
  82. _ASSERT( !RDVSD_ISLEGACY( m_CurrentVShaderHandle ),
  83. "FVF shader could not have provided a"
  84. " separate blend-index" );
  85. m_RefVP.m_blendindices.Init(
  86. (LPBYTE)Stream.m_pData + Element.m_dwOffset +
  87. dwStride * dwStartVertex, dwStride );
  88. break;
  89. case D3DVSDE_NORMAL:
  90. m_RefVP.m_normal.Init(
  91. (LPBYTE)Stream.m_pData + Element.m_dwOffset +
  92. dwStride * dwStartVertex, dwStride );
  93. break;
  94. case D3DVSDE_NORMAL2:
  95. m_RefVP.m_normal2.Init(
  96. (LPBYTE)Stream.m_pData + Element.m_dwOffset +
  97. dwStride * dwStartVertex, dwStride );
  98. break;
  99. case D3DVSDE_PSIZE:
  100. m_RefVP.m_pointsize.Init(
  101. (LPBYTE)Stream.m_pData + Element.m_dwOffset +
  102. dwStride * dwStartVertex, dwStride );
  103. break;
  104. case D3DVSDE_DIFFUSE:
  105. m_RefVP.m_diffuse.Init(
  106. (LPBYTE)Stream.m_pData + Element.m_dwOffset +
  107. dwStride * dwStartVertex, dwStride );
  108. break;
  109. case D3DVSDE_SPECULAR:
  110. m_RefVP.m_specular.Init(
  111. (LPBYTE)Stream.m_pData + Element.m_dwOffset +
  112. dwStride * dwStartVertex, dwStride );
  113. break;
  114. case D3DVSDE_TEXCOORD0:
  115. m_RefVP.m_tex[0].Init(
  116. (LPBYTE)Stream.m_pData + Element.m_dwOffset +
  117. dwStride * dwStartVertex, dwStride );
  118. break;
  119. case D3DVSDE_TEXCOORD1:
  120. m_RefVP.m_tex[1].Init(
  121. (LPBYTE)Stream.m_pData + Element.m_dwOffset +
  122. dwStride * dwStartVertex, dwStride );
  123. break;
  124. case D3DVSDE_TEXCOORD2:
  125. m_RefVP.m_tex[2].Init(
  126. (LPBYTE)Stream.m_pData + Element.m_dwOffset +
  127. dwStride * dwStartVertex, dwStride );
  128. break;
  129. case D3DVSDE_TEXCOORD3:
  130. m_RefVP.m_tex[3].Init(
  131. (LPBYTE)Stream.m_pData + Element.m_dwOffset +
  132. dwStride * dwStartVertex, dwStride );
  133. break;
  134. case D3DVSDE_TEXCOORD4:
  135. m_RefVP.m_tex[4].Init(
  136. (LPBYTE)Stream.m_pData + Element.m_dwOffset +
  137. dwStride * dwStartVertex, dwStride );
  138. break;
  139. case D3DVSDE_TEXCOORD5:
  140. m_RefVP.m_tex[5].Init(
  141. (LPBYTE)Stream.m_pData + Element.m_dwOffset +
  142. dwStride * dwStartVertex, dwStride );
  143. break;
  144. case D3DVSDE_TEXCOORD6:
  145. m_RefVP.m_tex[6].Init(
  146. (LPBYTE)Stream.m_pData + Element.m_dwOffset +
  147. dwStride * dwStartVertex, dwStride );
  148. break;
  149. case D3DVSDE_TEXCOORD7:
  150. m_RefVP.m_tex[7].Init(
  151. (LPBYTE)Stream.m_pData + Element.m_dwOffset +
  152. dwStride * dwStartVertex, dwStride );
  153. break;
  154. }
  155. }
  156. // If it is a FVF vertex shader and index-vertex blending is enabled
  157. // then the blend-indices are found in the last beta (which is the blend
  158. // weight) of the vertex.
  159. if( RDVSD_ISLEGACY( m_CurrentVShaderHandle ) &&
  160. (m_RefVP.m_dwTLState & RDPV_DOINDEXEDVERTEXBLEND) )
  161. {
  162. m_RefVP.m_blendindices.Init(
  163. (float *)m_RefVP.m_blendweights.GetFirst() +
  164. m_RefVP.m_numVertexBlends,
  165. m_RefVP.m_blendweights.GetStride() );
  166. }
  167. return S_OK;
  168. }
  169. ///////////////////////////////////////////////////////////////////////////////
  170. // Process primitives implementation:
  171. // 1) Compute FVF info
  172. // 2) Grow buffers to the requisite size
  173. // 3) Initialize clipping state
  174. // 4) Update T&L state
  175. // 5) Transform, Light and compute clipping for vertices
  176. // 6) Clip and Draw the primitives
  177. //
  178. ///////////////////////////////////////////////////////////////////////////////
  179. HRESULT
  180. RefDev::ProcessPrimitive( D3DPRIMITIVETYPE PrimType,
  181. DWORD StartVertex,
  182. DWORD cVertices,
  183. DWORD StartIndex,
  184. DWORD cIndices )
  185. {
  186. HRESULT hr = D3D_OK;
  187. DWORD dwVertexPoolSize = 0;
  188. // Save Prim Type for later use
  189. m_primType = PrimType;
  190. m_dwNumVertices = cVertices;
  191. m_dwStartVertex = StartVertex;
  192. m_dwNumIndices = cIndices;
  193. m_dwStartIndex = StartIndex;
  194. //
  195. // Update T&L state (must be before FVFData is set up)
  196. //
  197. // Update Lighting and related state and flags and computes Output FVF
  198. HR_RET( UpdateTLState() );
  199. //
  200. // Clipping information depends both on the output FVF computation
  201. // and the other State, so do it here after both have been computed
  202. //
  203. HR_RET( UpdateClipper() );
  204. //
  205. // Grow TLVArray if required
  206. //
  207. if( FAILED( m_TLVArray.Grow( m_dwNumVertices ) ) )
  208. {
  209. DPFERR( "Could not grow TL vertex buffer" );
  210. return DDERR_OUTOFMEMORY;
  211. }
  212. //
  213. // Transform, Light and compute clipping for vertices
  214. //
  215. DWORD clipIntersection = m_RefVP.ProcessVertices( m_qwFVFOut, m_TLVArray,
  216. m_dwNumVertices );
  217. if( m_primType == D3DPT_POINTLIST )
  218. {
  219. // We clip points by Z planes and user clip planes, because point
  220. // sprites could be still visible when a point is outside X or Y plane
  221. clipIntersection &= ~(RDCLIP_LEFT | RDCLIP_RIGHT |
  222. RDCLIP_TOP | RDCLIP_BOTTOM |
  223. RDCLIPGB_ALL);
  224. }
  225. if( clipIntersection )
  226. {
  227. // If the entire primitive lies outside the view frustum, quit
  228. // without drawing
  229. return D3D_OK;
  230. }
  231. //
  232. // Clip and Draw the primitives
  233. //
  234. if( m_dwNumIndices )
  235. {
  236. if( !NeedClipping(m_Clipper.UseGuardBand(), m_Clipper.m_clipUnion) )
  237. {
  238. if( m_IndexStream.m_dwStride == 4 )
  239. hr = DrawOneIndexedPrimitive(
  240. m_TLVArray,
  241. 0,
  242. (LPDWORD)m_IndexStream.m_pData,
  243. m_dwStartIndex,
  244. m_dwNumIndices,
  245. m_primType );
  246. else
  247. hr = DrawOneIndexedPrimitive(
  248. m_TLVArray,
  249. 0,
  250. (LPWORD)m_IndexStream.m_pData,
  251. m_dwStartIndex,
  252. m_dwNumIndices,
  253. m_primType );
  254. }
  255. else
  256. {
  257. if( m_IndexStream.m_dwStride == 4 )
  258. hr = m_Clipper.DrawOneIndexedPrimitive(
  259. m_TLVArray,
  260. 0,
  261. (LPDWORD)m_IndexStream.m_pData,
  262. m_dwStartIndex,
  263. m_dwNumIndices,
  264. m_primType );
  265. else
  266. hr = m_Clipper.DrawOneIndexedPrimitive(
  267. m_TLVArray,
  268. 0,
  269. (LPWORD)m_IndexStream.m_pData,
  270. m_dwStartIndex,
  271. m_dwNumIndices,
  272. m_primType );
  273. }
  274. }
  275. else
  276. {
  277. if( !NeedClipping((m_Clipper.UseGuardBand()), m_Clipper.m_clipUnion) )
  278. {
  279. hr = DrawOnePrimitive(
  280. m_TLVArray,
  281. 0,
  282. m_primType,
  283. m_dwNumVertices );
  284. }
  285. else
  286. {
  287. hr = m_Clipper.DrawOnePrimitive(
  288. m_TLVArray,
  289. 0,
  290. m_primType,
  291. m_dwNumVertices );
  292. }
  293. }
  294. return hr;
  295. }
  296. //---------------------------------------------------------------------
  297. // RefDev::UpdateTLState
  298. // Updates transform and lighting related state
  299. //---------------------------------------------------------------------
  300. HRESULT
  301. RefDev::UpdateTLState()
  302. {
  303. HRESULT hr = D3D_OK;
  304. UINT64 qwFVFIn = m_RefVP.m_qwFVFIn;
  305. //
  306. // Sort out vertex blending.
  307. //
  308. // Total number of floats/dwords provided per vertex according to
  309. // the FVF.
  310. DWORD numBetas = 0;
  311. if( (qwFVFIn & D3DFVF_POSITION_MASK) !=
  312. (D3DFVF_XYZ & D3DFVF_POSITION_MASK) )
  313. numBetas = ((qwFVFIn & D3DFVF_POSITION_MASK) >> 1) - 2;
  314. DWORD numWeights = GetRS()[D3DRENDERSTATE_VERTEXBLEND];
  315. // If tweening is enabled, there better be Position2 or Normal2
  316. if( numWeights == D3DVBF_TWEENING )
  317. {
  318. if( (qwFVFIn & (D3DFVFP_POSITION2 | D3DFVFP_NORMAL2)) == 0 )
  319. {
  320. DPFERR( "Tweening is enabled, but there is neither position2"
  321. " nor normal2 available\n" );
  322. return E_FAIL;
  323. }
  324. if( qwFVFIn & D3DFVFP_POSITION2 )
  325. m_RefVP.m_dwTLState |= RDPV_DOPOSITIONTWEENING;
  326. if( qwFVFIn & D3DFVFP_NORMAL2 )
  327. m_RefVP.m_dwTLState |= RDPV_DONORMALTWEENING;
  328. numWeights = 0;
  329. }
  330. else
  331. {
  332. m_RefVP.m_dwTLState &= ~(RDPV_DOPOSITIONTWEENING |
  333. RDPV_DONORMALTWEENING);
  334. }
  335. if( numWeights == D3DVBF_DISABLE )
  336. m_RefVP.m_dwTLState &= ~RDPV_DOINDEXEDVERTEXBLEND;
  337. if( numWeights == D3DVBF_0WEIGHTS ) numWeights = 0;
  338. if( m_RefVP.m_dwTLState & RDPV_DOINDEXEDVERTEXBLEND )
  339. {
  340. // If it is a FVF shader (legacy) the blend indices are provided as
  341. // the betas. There should be enough betas to cover this.
  342. if( RDVSD_ISLEGACY( m_CurrentVShaderHandle ) &&
  343. (numBetas < (numWeights + 1)) )
  344. {
  345. DPFERR( "Not enough blend-weights to do indexed vertex blending" );
  346. return E_FAIL;
  347. }
  348. else if( !RDVSD_ISLEGACY( m_CurrentVShaderHandle ) &&
  349. ((qwFVFIn & D3DFVFP_BLENDINDICES) == 0) )
  350. {
  351. DPFERR( "Blend-indices not provided" );
  352. return E_FAIL;
  353. }
  354. }
  355. else if( numWeights )
  356. {
  357. if( numBetas < numWeights )
  358. {
  359. DPFERR( "Not enough blend-weights to do vertex blending" );
  360. return E_FAIL;
  361. }
  362. }
  363. m_RefVP.m_numVertexBlends = numWeights;
  364. //
  365. // Check prim type to see if point size computation is needed
  366. // Need to set this before the transform state is set
  367. //
  368. m_RefVP.m_dwTLState &= ~(RDPV_DOCOMPUTEPOINTSIZE | RDPV_DOPOINTSCALE);
  369. switch(m_primType)
  370. {
  371. case D3DPT_POINTLIST:
  372. m_RefVP.m_dwTLState |= RDPV_DOCOMPUTEPOINTSIZE;
  373. if( GetRS()[D3DRS_POINTSCALEENABLE] )
  374. m_RefVP.m_dwTLState |= RDPV_DOPOINTSCALE;
  375. break;
  376. }
  377. // Fog or not:
  378. // Compute fog if: 1) Fogging is enabled
  379. // 2) VertexFog mode is not FOG_NONE
  380. // 3) TableFog mode is FOG_NONE
  381. // If both table and vertex fog are not FOG_NONE, table fog
  382. // is applied.
  383. if( GetRS()[D3DRENDERSTATE_FOGENABLE] &&
  384. GetRS()[D3DRENDERSTATE_FOGVERTEXMODE] &&
  385. !GetRS()[D3DRENDERSTATE_FOGTABLEMODE] )
  386. {
  387. m_RefVP.m_dwTLState |= RDPV_DOFOG;
  388. // Range Fog
  389. if( GetRS()[D3DRENDERSTATE_RANGEFOGENABLE] )
  390. {
  391. m_RefVP.m_dwTLState |= RDPV_RANGEFOG;
  392. }
  393. else
  394. {
  395. m_RefVP.m_dwTLState &= ~RDPV_RANGEFOG;
  396. }
  397. }
  398. else
  399. {
  400. m_RefVP.m_dwTLState &= ~(RDPV_DOFOG | RDPV_RANGEFOG);
  401. }
  402. //
  403. // Evaluate if any texture transform/gen is required. If so, then compute
  404. // the output Texture Coordinates
  405. //
  406. UpdateActiveTexStageCount();
  407. m_RefVP.m_dwNumActiveTextureStages = m_cActiveTextureStages;
  408. m_RefVP.m_dwTLState &= ~(RDPV_DOTEXGEN | RDPV_DOTEXXFORM |
  409. RDPV_NEEDEYENORMAL | RDPV_NEEDEYEXYZ);
  410. for( DWORD dwStage=0; dwStage<(DWORD)m_cActiveTextureStages; dwStage++ )
  411. {
  412. if( (GetTSS(dwStage)[D3DTSS_TEXTURETRANSFORMFLAGS]
  413. & ~D3DTTFF_PROJECTED) != D3DTTFF_DISABLE )
  414. {
  415. m_RefVP.m_dwTLState |= RDPV_DOTEXXFORM;
  416. }
  417. if( GetTSS(dwStage)[D3DTSS_TEXCOORDINDEX] & 0xffff0000 )
  418. {
  419. m_RefVP.m_dwTLState |= RDPV_DOTEXGEN;
  420. }
  421. }
  422. // Something changed in the transformation state
  423. // Recompute digested transform state
  424. HR_RET(m_RefVP.UpdateXformData());
  425. // Something changed in the lighting state
  426. if( (m_RefVP.m_dwTLState & RDPV_DOLIGHTING) &&
  427. (m_RefVP.m_dwDirtyFlags & RDPV_DIRTY_LIGHTING) )
  428. {
  429. RDLIGHTINGDATA& LData = m_RefVP.m_lighting;
  430. //
  431. // Compute Colorvertex flags only if the lighting is enabled
  432. //
  433. m_RefVP.m_dwTLState &= ~RDPV_COLORVERTEXFLAGS;
  434. LData.pAmbientSrc = &LData.matAmb;
  435. LData.pDiffuseSrc = &LData.matDiff;
  436. LData.pSpecularSrc = &LData.matSpec;
  437. LData.pEmissiveSrc = &LData.matEmis;
  438. LData.pDiffuseAlphaSrc = &LData.materialDiffAlpha;
  439. LData.pSpecularAlphaSrc = &LData.materialSpecAlpha;
  440. if( GetRS()[D3DRENDERSTATE_COLORVERTEX] )
  441. {
  442. switch( GetRS()[D3DRENDERSTATE_AMBIENTMATERIALSOURCE] )
  443. {
  444. case D3DMCS_MATERIAL:
  445. break;
  446. case D3DMCS_COLOR1:
  447. {
  448. if( qwFVFIn & D3DFVF_DIFFUSE )
  449. {
  450. m_RefVP.m_dwTLState |=
  451. (RDPV_VERTEXDIFFUSENEEDED | RDPV_COLORVERTEXAMB);
  452. LData.pAmbientSrc = &LData.vertexDiffuse;
  453. }
  454. }
  455. break;
  456. case D3DMCS_COLOR2:
  457. {
  458. if( qwFVFIn & D3DFVF_SPECULAR )
  459. {
  460. m_RefVP.m_dwTLState |=
  461. (RDPV_VERTEXSPECULARNEEDED | RDPV_COLORVERTEXAMB);
  462. LData.pAmbientSrc = &LData.vertexSpecular;
  463. }
  464. }
  465. break;
  466. }
  467. switch( GetRS()[D3DRENDERSTATE_DIFFUSEMATERIALSOURCE] )
  468. {
  469. case D3DMCS_MATERIAL:
  470. break;
  471. case D3DMCS_COLOR1:
  472. {
  473. if( qwFVFIn & D3DFVF_DIFFUSE )
  474. {
  475. m_RefVP.m_dwTLState |=
  476. (RDPV_VERTEXDIFFUSENEEDED | RDPV_COLORVERTEXDIFF);
  477. LData.pDiffuseSrc = &LData.vertexDiffuse;
  478. LData.pDiffuseAlphaSrc =
  479. &LData.vertexDiffAlpha;
  480. }
  481. }
  482. break;
  483. case D3DMCS_COLOR2:
  484. {
  485. if( qwFVFIn & D3DFVF_SPECULAR )
  486. {
  487. m_RefVP.m_dwTLState |=
  488. (RDPV_VERTEXSPECULARNEEDED | RDPV_COLORVERTEXDIFF);
  489. LData.pDiffuseSrc = &LData.vertexSpecular;
  490. LData.pDiffuseAlphaSrc =
  491. &LData.vertexSpecAlpha;
  492. }
  493. }
  494. break;
  495. }
  496. switch( GetRS()[D3DRENDERSTATE_SPECULARMATERIALSOURCE] )
  497. {
  498. case D3DMCS_MATERIAL:
  499. break;
  500. case D3DMCS_COLOR1:
  501. {
  502. if( qwFVFIn & D3DFVF_DIFFUSE )
  503. {
  504. m_RefVP.m_dwTLState |=
  505. (RDPV_VERTEXDIFFUSENEEDED | RDPV_COLORVERTEXSPEC);
  506. LData.pSpecularSrc = &LData.vertexDiffuse;
  507. LData.pSpecularAlphaSrc =
  508. &LData.vertexDiffAlpha;
  509. }
  510. }
  511. break;
  512. case D3DMCS_COLOR2:
  513. {
  514. if( qwFVFIn & D3DFVF_SPECULAR )
  515. {
  516. m_RefVP.m_dwTLState |=
  517. (RDPV_VERTEXSPECULARNEEDED | RDPV_COLORVERTEXSPEC);
  518. LData.pSpecularSrc = &LData.vertexSpecular;
  519. LData.pSpecularAlphaSrc =
  520. &LData.vertexSpecAlpha;
  521. }
  522. }
  523. break;
  524. }
  525. switch( GetRS()[D3DRENDERSTATE_EMISSIVEMATERIALSOURCE] )
  526. {
  527. case D3DMCS_MATERIAL:
  528. break;
  529. case D3DMCS_COLOR1:
  530. {
  531. if( qwFVFIn & D3DFVF_DIFFUSE )
  532. {
  533. m_RefVP.m_dwTLState |=
  534. (RDPV_VERTEXDIFFUSENEEDED | RDPV_COLORVERTEXEMIS);
  535. LData.pEmissiveSrc = &LData.vertexDiffuse;
  536. }
  537. }
  538. break;
  539. case D3DMCS_COLOR2:
  540. {
  541. if( qwFVFIn & D3DFVF_SPECULAR )
  542. {
  543. m_RefVP.m_dwTLState |=
  544. (RDPV_VERTEXSPECULARNEEDED | RDPV_COLORVERTEXEMIS);
  545. LData.pEmissiveSrc = &LData.vertexSpecular;
  546. }
  547. }
  548. break;
  549. }
  550. }
  551. // If specular is needed in the output and has been provided
  552. // in the input, force the copy of specular data
  553. if( qwFVFIn & D3DFVF_SPECULAR )
  554. {
  555. m_RefVP.m_dwTLState |= RDPV_VERTEXSPECULARNEEDED;
  556. }
  557. //
  558. // Update the remaining light state
  559. //
  560. HR_RET(m_RefVP.UpdateLightingData());
  561. }
  562. if( (m_RefVP.m_dwTLState & RDPV_DOFOG) &&
  563. (m_RefVP.m_dwDirtyFlags & RDPV_DIRTY_FOG) )
  564. {
  565. HR_RET(m_RefVP.UpdateFogData());
  566. }
  567. //
  568. // Compute output FVF
  569. //
  570. BOOL bFogEnabled = GetRS()[D3DRENDERSTATE_FOGENABLE];
  571. BOOL bSpecularEnabled = GetRS()[D3DRENDERSTATE_SPECULARENABLE];
  572. m_qwFVFOut = D3DFVF_XYZRHW;
  573. // If normal is present we have to compute specular and diffuse
  574. // Otherwise set these bits the same as input.
  575. // Not that normal should not be present for XYZRHW position type
  576. if( m_RefVP.m_dwTLState & RDPV_DOLIGHTING )
  577. {
  578. m_qwFVFOut |= D3DFVF_DIFFUSE | D3DFVF_SPECULAR;
  579. }
  580. else
  581. {
  582. m_qwFVFOut |= (qwFVFIn & (D3DFVF_DIFFUSE | D3DFVF_SPECULAR));
  583. }
  584. // Clear specular flag if specular disabled
  585. // else if( !this->rstates[D3DRENDERSTATE_SPECULARENABLE] )
  586. if( !bSpecularEnabled && ((qwFVFIn & D3DFVF_SPECULAR) == 0))
  587. {
  588. m_qwFVFOut &= ~D3DFVF_SPECULAR;
  589. }
  590. // Always set specular flag if fog is enabled
  591. // if( this->rstates[D3DRENDERSTATE_FOGENABLE] )
  592. if( bFogEnabled && (!GetRS()[D3DRENDERSTATE_FOGTABLEMODE]) )
  593. {
  594. m_qwFVFOut |= D3DFVFP_FOG;
  595. }
  596. // Reserve space for point size, if needed
  597. if( m_RefVP.m_dwTLState & RDPV_DOCOMPUTEPOINTSIZE )
  598. {
  599. m_qwFVFOut |= D3DFVF_PSIZE;
  600. }
  601. if( m_RefVP.m_dwTLState & (RDPV_DOTEXGEN | RDPV_DOTEXXFORM) )
  602. {
  603. // If there was any need for TexTransform or TexGen, we need to
  604. // override the TCI per stage.
  605. m_bOverrideTCI = TRUE;
  606. m_qwFVFOut |= (m_cActiveTextureStages << D3DFVF_TEXCOUNT_SHIFT);
  607. // Now compute the texture formats
  608. for( dwStage = 0; dwStage < (DWORD)m_cActiveTextureStages; dwStage++ )
  609. {
  610. DWORD dwTextureFormat = 0;
  611. DWORD TCI = GetTSS(dwStage)[D3DTSS_TEXCOORDINDEX];
  612. DWORD TexGenMode = TCI & ~0xFFFF;
  613. TCI &= 0xFFFF;
  614. switch( TexGenMode )
  615. {
  616. case D3DTSS_TCI_CAMERASPACENORMAL:
  617. dwTextureFormat = D3DFVF_TEXCOORDSIZE3(dwStage);
  618. m_RefVP.m_dwTLState |= RDPV_NEEDEYENORMAL;
  619. break;
  620. case D3DTSS_TCI_CAMERASPACEPOSITION:
  621. dwTextureFormat = D3DFVF_TEXCOORDSIZE3(dwStage);
  622. m_RefVP.m_dwTLState |= RDPV_NEEDEYEXYZ;
  623. break;
  624. case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
  625. dwTextureFormat = D3DFVF_TEXCOORDSIZE3(dwStage);
  626. m_RefVP.m_dwTLState |= (RDPV_NEEDEYENORMAL | RDPV_NEEDEYEXYZ);
  627. break;
  628. case 0: // No TexGen
  629. // Set back the input texture format
  630. dwTextureFormat =
  631. (D3DFVF_GETTEXCOORDSIZE( qwFVFIn, TCI ) << (dwStage*2 + 16));
  632. break;
  633. default:
  634. DPFERR( "Unknown TexGen mode" );
  635. return E_FAIL;
  636. }
  637. // Adjust the format for TexTransform
  638. DWORD TexXfmFlags =
  639. GetTSS(dwStage)[D3DTSS_TEXTURETRANSFORMFLAGS];
  640. if( TexXfmFlags )
  641. {
  642. switch( TexXfmFlags & ~D3DTTFF_PROJECTED )
  643. {
  644. case D3DTTFF_DISABLE:
  645. break;
  646. case D3DTTFF_COUNT1:
  647. dwTextureFormat = D3DFVF_TEXCOORDSIZE1( dwStage );
  648. break;
  649. case D3DTTFF_COUNT2:
  650. dwTextureFormat = D3DFVF_TEXCOORDSIZE2( dwStage );
  651. break;
  652. case D3DTTFF_COUNT3:
  653. dwTextureFormat = D3DFVF_TEXCOORDSIZE3( dwStage );
  654. break;
  655. case D3DTTFF_COUNT4:
  656. dwTextureFormat = D3DFVF_TEXCOORDSIZE4( dwStage );
  657. break;
  658. default:
  659. DPFERR( "Unknown dimension" );
  660. return E_FAIL;
  661. }
  662. }
  663. m_qwFVFOut |= dwTextureFormat;
  664. }
  665. }
  666. else
  667. {
  668. // Set up number of texture coordinates and copy texture formats
  669. DWORD numTex = FVF_TEXCOORD_NUMBER(qwFVFIn);
  670. m_qwFVFOut |= (numTex << D3DFVF_TEXCOUNT_SHIFT) |
  671. (qwFVFIn & 0xFFFF0000);
  672. }
  673. m_RefVP.m_qwFVFOut = m_qwFVFOut;
  674. //
  675. // Set up the strides for the vertex processing
  676. //
  677. return SetupStrides();
  678. }
  679. ///////////////////////////////////////////////////////////////////////////////
  680. // RefVP method implementations
  681. ///////////////////////////////////////////////////////////////////////////////
  682. //---------------------------------------------------------------------
  683. // RefVP::ProcessVertices
  684. //---------------------------------------------------------------------
  685. RDCLIPCODE
  686. RefVP::ProcessVertices( UINT64 outFVF, GArrayT<RDVertex>& VtxArray,
  687. DWORD count )
  688. {
  689. UINT64 inFVF = m_qwFVFIn;
  690. RefClipper& Clipper = m_pDev->GetClipper();
  691. DWORD flags = m_dwTLState;
  692. RDCLIPCODE clipIntersection = ~0;
  693. RDCLIPCODE clipUnion = 0;
  694. RDLIGHTINGELEMENT le;
  695. BOOL bVertexInEyeSpace = FALSE;
  696. DWORD dwCurrVtx = 0;
  697. RDVECTOR3* pPos = (RDVECTOR3 *)m_position.GetFirst();
  698. RDVECTOR3* pPos2 = (RDVECTOR3 *)m_position2.GetFirst();
  699. float* pBlendFactors = (float *)m_blendweights.GetFirst();
  700. DWORD* pBlendIndices = (DWORD *)m_blendindices.GetFirst();
  701. RDVECTOR3* pNormal = (RDVECTOR3 *)m_normal.GetFirst();
  702. RDVECTOR3* pNormal2 = (RDVECTOR3 *)m_normal2.GetFirst();
  703. DWORD* pDiffuse = (DWORD *)m_diffuse.GetFirst();
  704. DWORD* pSpecular = (DWORD *)m_specular.GetFirst();
  705. float* pPointSize = (float *)m_pointsize.GetFirst();
  706. float* pTex[8];
  707. RDVECTOR3 positionT, normalT; // Tweening results are saved here
  708. for( int t = 0; t < 8 ; t++ )
  709. pTex[t] = (float *)m_tex[t].GetFirst();
  710. //
  711. // Number of vertices to blend. i.e number of blend-matrices to
  712. // use is numVertexBlends+1.
  713. //
  714. int numVertexBlends = m_numVertexBlends;
  715. m_lighting.outDiffuse = RD_DEFAULT_DIFFUSE;
  716. m_lighting.outSpecular = RD_DEFAULT_SPECULAR;
  717. //
  718. // The main transform loop
  719. //
  720. for( DWORD i = count; i; i-- )
  721. {
  722. RDVertex& Vout = VtxArray[dwCurrVtx++];
  723. Vout.SetFVF( outFVF | D3DFVFP_CLIP );
  724. float x_clip=0.0f, y_clip=0.0f, z_clip=0.0f, w_clip=0.0f;
  725. float inv_w_clip=0.0f;
  726. float cumulBlend = 0; // Blend accumulated so far
  727. ZeroMemory( &le, sizeof(RDLIGHTINGELEMENT) );
  728. RDVECTOR3 ZeroNormal;
  729. if( pNormal == NULL )
  730. {
  731. pNormal = &ZeroNormal;
  732. }
  733. //
  734. // Transform vertex to the clipping space, and position and normal
  735. // into eye space, if needed.
  736. //
  737. // Tween the Position if needed
  738. if( flags & RDPV_DOPOSITIONTWEENING )
  739. {
  740. positionT.x = pPos->x * (1.0f - m_fTweenFactor) +
  741. pPos2->x * m_fTweenFactor;
  742. positionT.y = pPos->y * (1.0f - m_fTweenFactor) +
  743. pPos2->y * m_fTweenFactor;
  744. positionT.z = pPos->z * (1.0f - m_fTweenFactor) +
  745. pPos2->z * m_fTweenFactor;
  746. pPos = &positionT;
  747. }
  748. if( flags & RDPV_DONORMALTWEENING )
  749. {
  750. normalT.x = pNormal->x * (1.0f - m_fTweenFactor) +
  751. pNormal2->x * m_fTweenFactor;
  752. normalT.y = pNormal->y * (1.0f - m_fTweenFactor) +
  753. pNormal2->y * m_fTweenFactor;
  754. normalT.z = pNormal->z * (1.0f - m_fTweenFactor) +
  755. pNormal2->z * m_fTweenFactor;
  756. pNormal = &normalT;
  757. }
  758. for( int j=0; j<=numVertexBlends; j++)
  759. {
  760. float blend;
  761. if( numVertexBlends == 0 )
  762. {
  763. blend = 1.0f;
  764. }
  765. else if( j == numVertexBlends )
  766. {
  767. blend = 1.0f - cumulBlend;
  768. }
  769. else
  770. {
  771. blend = pBlendFactors[j];
  772. cumulBlend += pBlendFactors[j];
  773. }
  774. if( flags & (RDPV_DOCOMPUTEPOINTSIZE | RDPV_DOLIGHTING |
  775. RDPV_NEEDEYEXYZ) )
  776. {
  777. bVertexInEyeSpace = TRUE;
  778. if( flags & RDPV_DOINDEXEDVERTEXBLEND )
  779. {
  780. BYTE m = ((BYTE *)pBlendIndices)[j];
  781. UpdateWorld( m );
  782. le.dvPosition.x += (pPos->x*m_xfmToEye[m]._11 +
  783. pPos->y*m_xfmToEye[m]._21 +
  784. pPos->z*m_xfmToEye[m]._31 +
  785. m_xfmToEye[m]._41) * blend;
  786. le.dvPosition.y += (pPos->x*m_xfmToEye[m]._12 +
  787. pPos->y*m_xfmToEye[m]._22 +
  788. pPos->z*m_xfmToEye[m]._32 +
  789. m_xfmToEye[m]._42) * blend;
  790. le.dvPosition.z += (pPos->x*m_xfmToEye[m]._13 +
  791. pPos->y*m_xfmToEye[m]._23 +
  792. pPos->z*m_xfmToEye[m]._33 +
  793. m_xfmToEye[m]._43) * blend;
  794. }
  795. else
  796. {
  797. le.dvPosition.x += (pPos->x*m_xfmToEye[j]._11 +
  798. pPos->y*m_xfmToEye[j]._21 +
  799. pPos->z*m_xfmToEye[j]._31 +
  800. m_xfmToEye[j]._41) * blend;
  801. le.dvPosition.y += (pPos->x*m_xfmToEye[j]._12 +
  802. pPos->y*m_xfmToEye[j]._22 +
  803. pPos->z*m_xfmToEye[j]._32 +
  804. m_xfmToEye[j]._42) * blend;
  805. le.dvPosition.z += (pPos->x*m_xfmToEye[j]._13 +
  806. pPos->y*m_xfmToEye[j]._23 +
  807. pPos->z*m_xfmToEye[j]._33 +
  808. m_xfmToEye[j]._43) * blend;
  809. }
  810. }
  811. if( flags & (RDPV_DOLIGHTING | RDPV_NEEDEYENORMAL) )
  812. {
  813. if( flags & RDPV_DOINDEXEDVERTEXBLEND )
  814. {
  815. BYTE m = ((BYTE *)pBlendIndices)[j];
  816. UpdateWorld( m );
  817. le.dvNormal.x += (pNormal->x*m_xfmToEyeInv[m]._11 +
  818. pNormal->y*m_xfmToEyeInv[m]._12 +
  819. pNormal->z*m_xfmToEyeInv[m]._13) * blend;
  820. le.dvNormal.y += (pNormal->x*m_xfmToEyeInv[m]._21 +
  821. pNormal->y*m_xfmToEyeInv[m]._22 +
  822. pNormal->z*m_xfmToEyeInv[m]._23) * blend;
  823. le.dvNormal.z += (pNormal->x*m_xfmToEyeInv[m]._31 +
  824. pNormal->y*m_xfmToEyeInv[m]._32 +
  825. pNormal->z*m_xfmToEyeInv[m]._33) * blend;
  826. }
  827. else
  828. {
  829. // Transform vertex normal to the eye space
  830. // We use inverse transposed matrix
  831. le.dvNormal.x += (pNormal->x*m_xfmToEyeInv[j]._11 +
  832. pNormal->y*m_xfmToEyeInv[j]._12 +
  833. pNormal->z*m_xfmToEyeInv[j]._13) * blend;
  834. le.dvNormal.y += (pNormal->x*m_xfmToEyeInv[j]._21 +
  835. pNormal->y*m_xfmToEyeInv[j]._22 +
  836. pNormal->z*m_xfmToEyeInv[j]._23) * blend;
  837. le.dvNormal.z += (pNormal->x*m_xfmToEyeInv[j]._31 +
  838. pNormal->y*m_xfmToEyeInv[j]._32 +
  839. pNormal->z*m_xfmToEyeInv[j]._33) * blend;
  840. }
  841. }
  842. if( flags & RDPV_DOINDEXEDVERTEXBLEND )
  843. {
  844. BYTE m = ((BYTE *)pBlendIndices)[j];
  845. UpdateWorld( m );
  846. x_clip += (pPos->x*m_xfmCurrent[m]._11 +
  847. pPos->y*m_xfmCurrent[m]._21 +
  848. pPos->z*m_xfmCurrent[m]._31 +
  849. m_xfmCurrent[m]._41) * blend;
  850. y_clip += (pPos->x*m_xfmCurrent[m]._12 +
  851. pPos->y*m_xfmCurrent[m]._22 +
  852. pPos->z*m_xfmCurrent[m]._32 +
  853. m_xfmCurrent[m]._42) * blend;
  854. z_clip += (pPos->x*m_xfmCurrent[m]._13 +
  855. pPos->y*m_xfmCurrent[m]._23 +
  856. pPos->z*m_xfmCurrent[m]._33 +
  857. m_xfmCurrent[m]._43) * blend;
  858. w_clip += (pPos->x*m_xfmCurrent[m]._14 +
  859. pPos->y*m_xfmCurrent[m]._24 +
  860. pPos->z*m_xfmCurrent[m]._34 +
  861. m_xfmCurrent[m]._44) * blend;
  862. }
  863. else
  864. {
  865. // Apply WORLDj
  866. x_clip += (pPos->x*m_xfmCurrent[j]._11 +
  867. pPos->y*m_xfmCurrent[j]._21 +
  868. pPos->z*m_xfmCurrent[j]._31 +
  869. m_xfmCurrent[j]._41) * blend;
  870. y_clip += (pPos->x*m_xfmCurrent[j]._12 +
  871. pPos->y*m_xfmCurrent[j]._22 +
  872. pPos->z*m_xfmCurrent[j]._32 +
  873. m_xfmCurrent[j]._42) * blend;
  874. z_clip += (pPos->x*m_xfmCurrent[j]._13 +
  875. pPos->y*m_xfmCurrent[j]._23 +
  876. pPos->z*m_xfmCurrent[j]._33 +
  877. m_xfmCurrent[j]._43) * blend;
  878. w_clip += (pPos->x*m_xfmCurrent[j]._14 +
  879. pPos->y*m_xfmCurrent[j]._24 +
  880. pPos->z*m_xfmCurrent[j]._34 +
  881. m_xfmCurrent[j]._44) * blend;
  882. }
  883. }
  884. // Save the clip-coordinates
  885. Vout.m_clip_x = x_clip;
  886. Vout.m_clip_y = y_clip;
  887. Vout.m_clip_z = z_clip;
  888. Vout.m_clip_w = w_clip;
  889. if( (flags & RDPV_NORMALIZENORMALS) &&
  890. (flags & (RDPV_DOLIGHTING | RDPV_NEEDEYENORMAL)) )
  891. {
  892. Normalize(le.dvNormal);
  893. }
  894. FLOAT fPointSize = 0.0f;
  895. if( flags & RDPV_DOCOMPUTEPOINTSIZE )
  896. {
  897. FLOAT fDist = (FLOAT)sqrt(le.dvPosition.x*le.dvPosition.x +
  898. le.dvPosition.y*le.dvPosition.y +
  899. le.dvPosition.z*le.dvPosition.z);
  900. if( inFVF & D3DFVF_PSIZE )
  901. {
  902. fPointSize = *pPointSize;
  903. }
  904. else
  905. {
  906. // from D3DRENDERSTATE_POINTSIZE
  907. fPointSize = m_fPointSize;
  908. }
  909. if( flags & RDPV_DOPOINTSCALE )
  910. {
  911. fPointSize = (float)Clipper.m_Viewport.dwHeight*
  912. fPointSize*(FLOAT)sqrt(1.0f/
  913. (m_fPointAttA + m_fPointAttB*fDist +
  914. m_fPointAttC*fDist*fDist));
  915. }
  916. fPointSize = max(m_fPointSizeMin, fPointSize);
  917. fPointSize = min(m_fPointSizeMax, fPointSize);
  918. FLOAT *pfSOut = &Vout.m_pointsize;
  919. *pfSOut = fPointSize;
  920. }
  921. //
  922. // Compute clip codes if needed
  923. //
  924. if( flags & RDPV_DOCLIPPING )
  925. {
  926. RDCLIPCODE clip = Clipper.ComputeClipCodes( &clipIntersection,
  927. &clipUnion, x_clip,
  928. y_clip, z_clip,
  929. w_clip);
  930. if( clip == 0 )
  931. {
  932. Vout.m_clip = 0;
  933. inv_w_clip = D3DVAL(1)/w_clip;
  934. }
  935. else
  936. {
  937. if( Clipper.UseGuardBand() )
  938. {
  939. if( (clip & ~RDCLIP_INGUARDBAND) == 0 )
  940. {
  941. // If vertex is inside the guardband we have to compute
  942. // screen coordinates
  943. inv_w_clip = D3DVAL(1)/w_clip;
  944. Vout.m_clip = (RDCLIPCODE)clip;
  945. goto l_DoScreenCoord;
  946. }
  947. }
  948. Vout.m_clip = (RDCLIPCODE)clip;
  949. // If vertex is outside the frustum we can not compute screen
  950. // coordinates. skip to lighting
  951. #if 0
  952. Vout.m_pos.x = x_clip;
  953. Vout.m_pos.y = y_clip;
  954. Vout.m_pos.z = z_clip;
  955. Vout.m_rhw = w_clip;
  956. #endif
  957. goto l_DoLighting;
  958. }
  959. }
  960. else
  961. {
  962. // We have to check this only for DONOTCLIP case, because otherwise
  963. // the vertex with "we = 0" will be clipped and screen coordinates
  964. // will not be computed
  965. // "clip" is not zero, if "we" is zero.
  966. if( !FLOAT_EQZ(w_clip) )
  967. inv_w_clip = D3DVAL(1)/w_clip;
  968. else
  969. inv_w_clip = __HUGE_PWR2;
  970. }
  971. l_DoScreenCoord:
  972. Vout.m_pos.x = x_clip * inv_w_clip * Clipper.scaleX +
  973. Clipper.offsetX;
  974. Vout.m_pos.y = y_clip * inv_w_clip * Clipper.scaleY +
  975. Clipper.offsetY;
  976. Vout.m_pos.z = z_clip * inv_w_clip * Clipper.scaleZ +
  977. Clipper.offsetZ;
  978. Vout.m_rhw = inv_w_clip;
  979. l_DoLighting:
  980. if( flags & RDPV_DOLIGHTING )
  981. {
  982. bVertexInEyeSpace = TRUE;
  983. //
  984. // If Diffuse color is needed, extract it for color vertex.
  985. //
  986. if( flags & RDPV_VERTEXDIFFUSENEEDED )
  987. {
  988. const DWORD color = *pDiffuse;
  989. MakeRDCOLOR3(&m_lighting.vertexDiffuse, color);
  990. m_lighting.vertexDiffAlpha = color & 0xff000000;
  991. }
  992. //
  993. // If Specular color is needed and provided
  994. // , extract it for color vertex.
  995. //
  996. if( flags & RDPV_VERTEXSPECULARNEEDED )
  997. {
  998. const DWORD color = *pSpecular;
  999. MakeRDCOLOR3(&m_lighting.vertexSpecular, color);
  1000. m_lighting.vertexSpecAlpha = color & 0xff000000;
  1001. }
  1002. //
  1003. // Light the vertex
  1004. //
  1005. LightVertex( &le );
  1006. if( outFVF & D3DFVFP_FOG )
  1007. {
  1008. Vout.m_fog =
  1009. (FLOAT)RGBA_GETALPHA( *(m_lighting.pSpecularAlphaSrc) )/255.0f;
  1010. }
  1011. }
  1012. else if( inFVF & (D3DFVF_DIFFUSE | D3DFVF_SPECULAR) )
  1013. {
  1014. if( inFVF & D3DFVF_DIFFUSE )
  1015. m_lighting.outDiffuse = *pDiffuse;
  1016. if( inFVF & D3DFVF_SPECULAR )
  1017. {
  1018. m_lighting.outSpecular = *pSpecular;
  1019. if( outFVF & D3DFVFP_FOG )
  1020. {
  1021. Vout.m_fog = (FLOAT)RGBA_GETALPHA( *pSpecular )/255.0f;
  1022. }
  1023. }
  1024. }
  1025. //
  1026. // Compute Vertex Fog if needed
  1027. //
  1028. if( flags & RDPV_DOFOG )
  1029. {
  1030. FogVertex( Vout, *pPos, &le, numVertexBlends,
  1031. pBlendFactors, bVertexInEyeSpace );
  1032. }
  1033. if( outFVF & D3DFVF_DIFFUSE )
  1034. {
  1035. MakeRDCOLOR4( &Vout.m_diffuse, m_lighting.outDiffuse );
  1036. }
  1037. if( outFVF & D3DFVF_SPECULAR )
  1038. {
  1039. MakeRDCOLOR4( &Vout.m_specular, m_lighting.outSpecular );
  1040. }
  1041. if( flags & (RDPV_DOTEXGEN | RDPV_DOTEXXFORM) )
  1042. {
  1043. for( DWORD dwStage = 0;
  1044. dwStage < m_dwNumActiveTextureStages;
  1045. dwStage++ )
  1046. {
  1047. DWORD TexXfmFlags =
  1048. m_pDev->GetTSS(dwStage)[D3DTSS_TEXTURETRANSFORMFLAGS];
  1049. DWORD TCI =
  1050. m_pDev->GetTSS(dwStage)[D3DTSS_TEXCOORDINDEX];
  1051. DWORD TexGenMode = TCI & ~0xFFFF;
  1052. TCI &= 0xFFFF;
  1053. // Perform TexGen
  1054. switch( TexGenMode )
  1055. {
  1056. case D3DTSS_TCI_CAMERASPACENORMAL:
  1057. Vout.m_tex[dwStage].x = le.dvNormal.x;
  1058. Vout.m_tex[dwStage].y = le.dvNormal.y;
  1059. Vout.m_tex[dwStage].z = le.dvNormal.z;
  1060. Vout.m_tex[dwStage].w = 1.0f;
  1061. break;
  1062. case D3DTSS_TCI_CAMERASPACEPOSITION:
  1063. Vout.m_tex[dwStage].x = le.dvPosition.x;
  1064. Vout.m_tex[dwStage].y = le.dvPosition.y;
  1065. Vout.m_tex[dwStage].z = le.dvPosition.z;
  1066. Vout.m_tex[dwStage].w = 1.0f;
  1067. break;
  1068. case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
  1069. {
  1070. FLOAT fNX = le.dvNormal.x;
  1071. FLOAT fNY = le.dvNormal.y;
  1072. FLOAT fNZ = le.dvNormal.z;
  1073. FLOAT fNorm = 0;
  1074. if( m_pDev->GetRS()[D3DRENDERSTATE_LOCALVIEWER] == TRUE )
  1075. {
  1076. FLOAT fX = le.dvPosition.x;
  1077. FLOAT fY = le.dvPosition.y;
  1078. FLOAT fZ = le.dvPosition.z;
  1079. // have to normalize before we reflect,
  1080. // result will be normalized
  1081. FLOAT fDist = (FLOAT)sqrt(fX*fX + fY*fY + fZ*fZ);
  1082. if( FLOAT_NEZ( fDist ) )
  1083. {
  1084. fNorm = 1.0f/fDist;
  1085. }
  1086. fX *= fNorm; fY *= fNorm; fZ *= fNorm;
  1087. FLOAT fDot2 = 2.0f*(fX*fNX + fY*fNY + fZ*fNZ);
  1088. Vout.m_tex[dwStage].x = fX - fNX*fDot2;
  1089. Vout.m_tex[dwStage].y = fY - fNY*fDot2;
  1090. Vout.m_tex[dwStage].z = fZ - fNZ*fDot2;
  1091. }
  1092. else
  1093. {
  1094. FLOAT fDot2 = 2.0f*fNZ;
  1095. Vout.m_tex[dwStage].x = -fNX*fDot2;
  1096. Vout.m_tex[dwStage].y = -fNY*fDot2;
  1097. Vout.m_tex[dwStage].z = 1.f - fNZ*fDot2;
  1098. }
  1099. Vout.m_tex[dwStage].w = 1.0f;
  1100. break;
  1101. }
  1102. case 0: // No TexGen
  1103. {
  1104. // Copy the tex coordinate for this stage
  1105. DWORD n = GetTexCoordDim( inFVF, TCI );
  1106. float *pCoord = (float *)&Vout.m_tex[dwStage];
  1107. for( DWORD j = 0; j < n; j++ )
  1108. {
  1109. pCoord[j] = pTex[TCI][j];
  1110. }
  1111. if( n < 4 ) pCoord[n] = 1.0f;
  1112. for( j = n+1; j < 4; j++ ) pCoord[j] = 0.0f;
  1113. break;
  1114. }
  1115. default:
  1116. DPFERR( "Unknown TexGen mode" );
  1117. return E_FAIL;
  1118. }
  1119. // Perform TexTransform
  1120. if( ( TexXfmFlags & ~D3DTTFF_PROJECTED ) != D3DTTFF_DISABLE )
  1121. {
  1122. LPD3DMATRIX pM = &m_xfmTex[dwStage];
  1123. FLOAT fX = Vout.m_tex[dwStage].x;
  1124. FLOAT fY = Vout.m_tex[dwStage].y;
  1125. FLOAT fZ = Vout.m_tex[dwStage].z;
  1126. FLOAT fW = Vout.m_tex[dwStage].w;
  1127. FLOAT fXout = fX*pM->_11 + fY*pM->_21 + fZ*pM->_31 +
  1128. fW*pM->_41;
  1129. FLOAT fYout = fX*pM->_12 + fY*pM->_22 + fZ*pM->_32 +
  1130. fW*pM->_42;
  1131. FLOAT fZout = fX*pM->_13 + fY*pM->_23 + fZ*pM->_33 +
  1132. fW*pM->_43;
  1133. FLOAT fWout = fX*pM->_14 + fY*pM->_24 + fZ*pM->_34 +
  1134. fW*pM->_44;
  1135. Vout.m_tex[dwStage].x = fXout;
  1136. Vout.m_tex[dwStage].y = fYout;
  1137. Vout.m_tex[dwStage].z = fZout;
  1138. Vout.m_tex[dwStage].w = fWout;
  1139. }
  1140. }
  1141. }
  1142. else
  1143. {
  1144. // Copy the textures over
  1145. // If there is no TexGen or TexTransform
  1146. DWORD i, j;
  1147. DWORD numTex = FVF_TEXCOORD_NUMBER(outFVF);
  1148. for( i = 0; i < numTex; i++ )
  1149. {
  1150. DWORD n = GetTexCoordDim( outFVF, i );
  1151. // DWORD n = (DWORD)(m_dwTexCoordSizeArray[i] >> 2);
  1152. float *pCoord = (float *)&Vout.m_tex[i];
  1153. for( j = 0; j < n; j++ )
  1154. {
  1155. pCoord[j] = pTex[i][j];
  1156. }
  1157. }
  1158. }
  1159. //
  1160. // Update the current pointers
  1161. //
  1162. pPos = (RDVECTOR3 *)m_position.Next();
  1163. pPos2 = (RDVECTOR3 *)m_position2.Next();
  1164. pBlendFactors = (float *)m_blendweights.Next();
  1165. pBlendIndices = (DWORD *)m_blendindices.Next();
  1166. pNormal = (RDVECTOR3 *)m_normal.Next();
  1167. pNormal2 = (RDVECTOR3 *)m_normal2.Next();
  1168. pDiffuse = (DWORD *)m_diffuse.Next();
  1169. pSpecular = (DWORD *)m_specular.Next();
  1170. pPointSize = (float *)m_pointsize.Next();
  1171. for( t = 0; t < 8; t++ )
  1172. pTex[t] = (float *)m_tex[t].Next();
  1173. }
  1174. if( flags & RDPV_DOCLIPPING )
  1175. {
  1176. Clipper.m_clipIntersection = clipIntersection;
  1177. Clipper.m_clipUnion = clipUnion;
  1178. }
  1179. else
  1180. {
  1181. Clipper.m_clipIntersection = 0;
  1182. Clipper.m_clipUnion = 0;
  1183. }
  1184. // Returns whether all the vertices were off screen
  1185. return Clipper.m_clipIntersection;
  1186. }
  1187. ///////////////////////////////////////////////////////////////////////////////
  1188. ///////////////////////////////////////////////////////////////////////////////