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.

350 lines
11 KiB

  1. /*==========================================================================;
  2. *
  3. * Copyright (C) 1995 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: light.c
  6. * Content: Direct3D light management
  7. *@@BEGIN_MSINTERNAL
  8. *
  9. * History:
  10. * Date By Reason
  11. * ==== == ======
  12. * 11/11/95 stevela Initial rev with this header.
  13. * Light handling changed.
  14. *@@END_MSINTERNAL
  15. *
  16. ***************************************************************************/
  17. /*
  18. * Create an api for the Direct3DLight object
  19. */
  20. #include "pch.cpp"
  21. #pragma hdrstop
  22. HRESULT
  23. hookLightToD3D(LPDIRECT3DI lpD3DI,
  24. LPDIRECT3DLIGHTI lpD3DLight)
  25. {
  26. LIST_INSERT_ROOT(&lpD3DI->lights, lpD3DLight, list);
  27. lpD3DLight->lpDirect3DI = lpD3DI;
  28. lpD3DI->numLights++;
  29. return (D3D_OK);
  30. }
  31. HRESULT D3DAPI DIRECT3DLIGHTI::Initialize(LPDIRECT3D lpD3D)
  32. {
  33. return DDERR_ALREADYINITIALIZED;
  34. }
  35. void inverseRotateVector(D3DVECTOR* d, D3DVECTOR* v, D3DMATRIX* M)
  36. {
  37. D3DVALUE vx = v->x;
  38. D3DVALUE vy = v->y;
  39. D3DVALUE vz = v->z;
  40. d->x = vx * M->_11 + vy * M->_12 + vz * M->_13;
  41. d->y = vx * M->_21 + vy * M->_22 + vz * M->_23;
  42. d->z = vx * M->_31 + vy * M->_32 + vz * M->_33;
  43. }
  44. void inverseTransformVector(D3DVECTOR* d, D3DVECTOR* v, D3DMATRIX* M)
  45. {
  46. D3DVALUE vx = v->x;
  47. D3DVALUE vy = v->y;
  48. D3DVALUE vz = v->z;
  49. vx -= M->_41; vy -= M->_42; vz -= M->_43;
  50. d->x = vx * M->_11 + vy * M->_12 + vz * M->_13;
  51. d->y = vx * M->_21 + vy * M->_22 + vz * M->_23;
  52. d->z = vx * M->_31 + vy * M->_32 + vz * M->_33;
  53. }
  54. void D3DI_UpdateLightInternal(LPDIRECT3DLIGHTI lpLight)
  55. {
  56. LPDIRECT3DVIEWPORTI lpViewI = lpLight->lpD3DViewportI;
  57. LPD3DLIGHT2 lpLight2 = (D3DLIGHT2 *)&lpLight->dlLight;
  58. if (sizeof(D3DLIGHT) == lpLight->dlLight.dwSize)
  59. {
  60. lpLight->diLightData.version = 1;
  61. lpLight->diLightData.flags = D3DLIGHT_ACTIVE;
  62. } else {
  63. lpLight->diLightData.version = 2;
  64. lpLight->diLightData.flags = lpLight2->dwFlags;
  65. }
  66. lpLight->diLightData.valid = TRUE;
  67. lpLight->diLightData.type = lpLight->dlLight.dltType;
  68. lpLight->diLightData.red = lpLight->dlLight.dcvColor.r;
  69. lpLight->diLightData.green = lpLight->dlLight.dcvColor.g;
  70. lpLight->diLightData.blue = lpLight->dlLight.dcvColor.b;
  71. lpLight->diLightData.position.x = lpLight->dlLight.dvPosition.x;
  72. lpLight->diLightData.position.y = lpLight->dlLight.dvPosition.y;
  73. lpLight->diLightData.position.z = lpLight->dlLight.dvPosition.z;
  74. lpLight->diLightData.direction.x = lpLight->dlLight.dvDirection.x;
  75. lpLight->diLightData.direction.y = lpLight->dlLight.dvDirection.y;
  76. lpLight->diLightData.direction.z = lpLight->dlLight.dvDirection.z;
  77. lpLight->diLightData.attenuation0 = lpLight->dlLight.dvAttenuation0;
  78. lpLight->diLightData.attenuation1 = lpLight->dlLight.dvAttenuation1;
  79. lpLight->diLightData.attenuation2 = lpLight->dlLight.dvAttenuation2;
  80. VecNormalize(lpLight->diLightData.direction);
  81. lpLight->diLightData.range = lpLight->dlLight.dvRange;
  82. lpLight->diLightData.range_squared = lpLight->dlLight.dvRange * lpLight->dlLight.dvRange;
  83. lpLight->diLightData.shade = lpLight->dlLight.dcvColor.r * 0.3f +
  84. lpLight->dlLight.dcvColor.g * 0.59f +
  85. lpLight->dlLight.dcvColor.b * 0.11f;
  86. if (lpLight->dlLight.dltType == D3DLIGHT_SPOT)
  87. {
  88. lpLight->diLightData.cos_theta_by_2 = (float)cos(lpLight->dlLight.dvTheta / 2.0);
  89. lpLight->diLightData.cos_phi_by_2 = (float)cos(lpLight->dlLight.dvPhi / 2.0);
  90. if (lpLight->diLightData.version == 1)
  91. {
  92. if (lpLight->diLightData.cos_phi_by_2 < lpLight->diLightData.cos_theta_by_2)
  93. {
  94. lpLight->diLightData.falloff =
  95. 1.0f / (lpLight->diLightData.cos_theta_by_2 -
  96. lpLight->diLightData.cos_phi_by_2);
  97. }
  98. else
  99. {
  100. lpLight->diLightData.falloff = DTOVAL(0.0);
  101. }
  102. }
  103. else
  104. {
  105. lpLight->diLightData.falloff = lpLight->dlLight.dvFalloff;
  106. lpLight->diLightData.inv_theta_minus_phi = lpLight->diLightData.cos_theta_by_2 -
  107. lpLight->diLightData.cos_phi_by_2;
  108. if (lpLight->diLightData.inv_theta_minus_phi != 0.0)
  109. {
  110. lpLight->diLightData.inv_theta_minus_phi = 1.0f/lpLight->diLightData.inv_theta_minus_phi;
  111. }
  112. else
  113. {
  114. lpLight->diLightData.inv_theta_minus_phi = 1.0f;
  115. }
  116. }
  117. }
  118. /* set internal flags */
  119. if (lpLight->diLightData.version != 1)
  120. {
  121. if (lpLight->diLightData.attenuation0 != 0.0)
  122. {
  123. lpLight->diLightData.flags |= D3DLIGHTI_ATT0_IS_NONZERO;
  124. }
  125. if (lpLight->diLightData.attenuation1 != 0.0)
  126. {
  127. lpLight->diLightData.flags |= D3DLIGHTI_ATT1_IS_NONZERO;
  128. }
  129. if (lpLight->diLightData.attenuation2 != 0.0)
  130. {
  131. lpLight->diLightData.flags |= D3DLIGHTI_ATT2_IS_NONZERO;
  132. }
  133. if (lpLight->diLightData.falloff == 1.0)
  134. {
  135. lpLight->diLightData.flags |= D3DLIGHTI_LINEAR_FALLOFF;
  136. }
  137. }
  138. if (lpViewI)
  139. {
  140. lpViewI->bLightsChanged = TRUE;
  141. }
  142. }
  143. /*
  144. * Create the Light
  145. */
  146. #undef DPF_MODNAME
  147. #define DPF_MODNAME "Direct3D::CreateLight"
  148. HRESULT D3DAPI
  149. DIRECT3DI::CreateLight(LPDIRECT3DLIGHT* lplpLight,
  150. IUnknown* pUnkOuter)
  151. {
  152. LPDIRECT3DLIGHTI lpLight;
  153. HRESULT ret;
  154. if(pUnkOuter != NULL) {
  155. return CLASS_E_NOAGGREGATION;
  156. }
  157. ret = D3D_OK;
  158. CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
  159. // Release in the destructor
  160. /*
  161. * validate parms
  162. */
  163. if (!VALID_DIRECT3D3_PTR(this)) {
  164. D3D_ERR( "Invalid Direct3D pointer" );
  165. return DDERR_INVALIDOBJECT;
  166. }
  167. if (!VALID_OUTPTR(lplpLight)) {
  168. D3D_ERR( "Invalid pointer to pointer" );
  169. return DDERR_INVALIDPARAMS;
  170. }
  171. *lplpLight = NULL;
  172. /*
  173. * setup the object
  174. */
  175. lpLight = static_cast<LPDIRECT3DLIGHTI>(new DIRECT3DLIGHTI);
  176. if (!lpLight) {
  177. D3D_ERR("failed to allocate space for object");
  178. return DDERR_OUTOFMEMORY;
  179. }
  180. /*
  181. * Put this device in the list of those owned by the
  182. * Direct3Dobject
  183. */
  184. ret = hookLightToD3D(this, lpLight);
  185. if (ret != D3D_OK) {
  186. D3D_ERR("failed to associate light to Direct3D");
  187. D3DFree(lpLight);
  188. return ret;
  189. }
  190. *lplpLight = (LPDIRECT3DLIGHT)lpLight;
  191. return (D3D_OK);
  192. }
  193. DIRECT3DLIGHTI::DIRECT3DLIGHTI()
  194. {
  195. lpD3DViewportI = NULL;
  196. memset(&dlLight, 0, sizeof(D3DLIGHT2));
  197. memset(&diLightData, 0, sizeof(D3DI_LIGHT)); // Internal representation of light
  198. refCnt = 1;
  199. }
  200. #undef DPF_MODNAME
  201. #define DPF_MODNAME "Direct3DLight::SetLight"
  202. HRESULT D3DAPI
  203. DIRECT3DLIGHTI::SetLight(LPD3DLIGHT lpData)
  204. {
  205. HRESULT ret;
  206. ret = D3D_OK;
  207. CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
  208. // Release in the destructor
  209. /*
  210. * validate parms
  211. */
  212. TRY
  213. {
  214. if (!VALID_DIRECT3DLIGHT_PTR(this)) {
  215. D3D_ERR( "Invalid Direct3DLight pointer" );
  216. return DDERR_INVALIDOBJECT;
  217. }
  218. if (!VALID_D3DLIGHT_PTR(lpData) && !VALID_D3DLIGHT2_PTR(lpData)) {
  219. D3D_ERR( "Invalid D3DLIGHT pointer" );
  220. return DDERR_INVALIDPARAMS;
  221. }
  222. if (lpData->dwSize == sizeof(D3DLIGHT2)) {
  223. if (lpData->dltType != D3DLIGHT_POINT &&
  224. lpData->dltType != D3DLIGHT_SPOT &&
  225. lpData->dltType != D3DLIGHT_DIRECTIONAL &&
  226. lpData->dltType != D3DLIGHT_PARALLELPOINT) {
  227. D3D_ERR( "Invalid D3DLIGHT type" );
  228. return DDERR_INVALIDPARAMS;
  229. }
  230. if (lpData->dvRange < 0.0f || lpData->dvRange > D3DLIGHT_RANGE_MAX) {
  231. D3D_ERR( "Invalid D3DLIGHT range" );
  232. return DDERR_INVALIDPARAMS;
  233. }
  234. if (lpData->dltType == D3DLIGHT_SPOT || lpData->dltType == D3DLIGHT_DIRECTIONAL) {
  235. float magnitude;
  236. magnitude = lpData->dvDirection.x * lpData->dvDirection.x +
  237. lpData->dvDirection.y * lpData->dvDirection.y +
  238. lpData->dvDirection.z * lpData->dvDirection.z;
  239. if (magnitude < 0.00001f) {
  240. D3D_ERR( "Invalid D3DLIGHT direction" );
  241. return DDERR_INVALIDPARAMS;
  242. }
  243. if (lpData->dltType == D3DLIGHT_SPOT) {
  244. if (lpData->dvPhi < 0.0f) {
  245. D3D_ERR( "Invalid D3DLIGHT Phi angle, must be >= 0" );
  246. return DDERR_INVALIDPARAMS;
  247. }
  248. if (lpData->dvPhi > 3.1415927f) {
  249. D3D_ERR( "Invalid D3DLIGHT Phi angle, must be <= pi" );
  250. return DDERR_INVALIDPARAMS;
  251. }
  252. if (lpData->dvTheta < 0.0f) {
  253. D3D_ERR( "Invalid D3DLIGHT Theta angle, must be >= 0" );
  254. return DDERR_INVALIDPARAMS;
  255. }
  256. if (lpData->dvTheta > lpData->dvPhi) {
  257. D3D_ERR( "Invalid D3DLIGHT Theta angle, must be <= Phi" );
  258. return DDERR_INVALIDPARAMS;
  259. }
  260. }
  261. }
  262. }
  263. }
  264. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  265. {
  266. D3D_ERR( "Exception encountered validating parameters" );
  267. return DDERR_INVALIDPARAMS;
  268. }
  269. /* use memcpy so this works with either D3DLIGHT or D3DLIGHT2 */
  270. memcpy(&this->dlLight, lpData, lpData->dwSize);
  271. D3DI_UpdateLightInternal(this);
  272. return ret;
  273. }
  274. #undef DPF_MODNAME
  275. #define DPF_MODNAME "Direct3DLight::GetLight"
  276. HRESULT D3DAPI
  277. DIRECT3DLIGHTI::GetLight(LPD3DLIGHT lpData)
  278. {
  279. HRESULT ret;
  280. ret = D3D_OK;
  281. CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
  282. // Release in the destructor
  283. /*
  284. * validate parms
  285. */
  286. TRY
  287. {
  288. if (!VALID_DIRECT3DLIGHT_PTR(this)) {
  289. D3D_ERR( "Invalid Direct3DLight pointer" );
  290. return DDERR_INVALIDOBJECT;
  291. }
  292. if (!VALID_D3DLIGHT_PTR(lpData) && !VALID_D3DLIGHT2_PTR(lpData)) {
  293. D3D_ERR( "Invalid D3DLIGHT pointer" );
  294. return DDERR_INVALIDPARAMS;
  295. }
  296. }
  297. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  298. {
  299. D3D_ERR( "Exception encountered validating parameters" );
  300. return DDERR_INVALIDPARAMS;
  301. }
  302. /* use memcpy so this works with either D3DLIGHT or D3DLIGHT2 */
  303. memcpy(lpData, &this->dlLight, this->dlLight.dwSize);
  304. return (ret);
  305. }