From 8898ad9b25fca6afe2374d293a981db02a83d7e9 Mon Sep 17 00:00:00 2001 From: "FWoltermann@gmail.com" Date: Thu, 31 May 2012 14:46:27 +0000 Subject: Committing the documentation to svn to have it accessible online --- Doc/doxygen/html/_video_d_x9_8cpp_source.html | 3735 +++++++++++++++++++++++++ 1 file changed, 3735 insertions(+) create mode 100644 Doc/doxygen/html/_video_d_x9_8cpp_source.html (limited to 'Doc/doxygen/html/_video_d_x9_8cpp_source.html') diff --git a/Doc/doxygen/html/_video_d_x9_8cpp_source.html b/Doc/doxygen/html/_video_d_x9_8cpp_source.html new file mode 100644 index 0000000..ad7ad40 --- /dev/null +++ b/Doc/doxygen/html/_video_d_x9_8cpp_source.html @@ -0,0 +1,3735 @@ + + + + + +Starshatter_Open: D:/SRC/StarshatterSVN/nGenEx/VideoDX9.cpp Source File + + + + + + + + + + + + + +
+
+ + + + + + +
+
Starshatter_Open +
+
Open source Starshatter engine
+
+
+ + + + + +
+
+ +
+
+
+ +
+ + + + +
+ +
+ +
+
+
VideoDX9.cpp
+
+
+Go to the documentation of this file.
1 /* Project nGenEx
+
2  Destroyer Studios LLC
+
3  Copyright © 1997-2004. All Rights Reserved.
+
4 
+
5  SUBSYSTEM: nGenEx.lib
+
6  FILE: VideoDX9.cpp
+
7  AUTHOR: John DiCamillo
+
8 
+
9 
+
10  OVERVIEW
+
11  ========
+
12  Direct3D Video class for DirectX 9
+
13 */
+
14 
+
15 #include "MemDebug.h"
+
16 #include "VideoDX9.h"
+
17 #include "VideoDX9Enum.h"
+
18 #include "VideoDX9VertexBuffer.h"
+
19 #include "TexDX9.h"
+
20 #include "TexCubeDX9.h"
+
21 #include "Camera.h"
+
22 #include "Color.h"
+
23 #include "DataLoader.h"
+
24 #include "Polygon.h"
+
25 #include "Light.h"
+
26 #include "Solid.h"
+
27 
+
28 // +--------------------------------------------------------------------+
+
29 
+
30 void Print(const char* msg, ...);
+
31 char* D3DErrStr(HRESULT dderr);
+
32 void VideoDX9Error(const char* msg, HRESULT dderr);
+
33 static TexCacheDX9* texcache = 0;
+
34 static TexCubeDX9* environment_cube = 0;
+
35 static bool surface_has_tangent_data = false;
+
36 static Light* main_light;
+
37 static Light* back_light;
+
38 static D3DXMATRIX matrixWorld;
+
39 static D3DXMATRIX matrixView;
+
40 static D3DXMATRIX matrixProj;
+
41 static D3DXMATRIX matrixWorldInverse;
+
42 
+
43 extern int VD3D_describe_things;
+
44 
+
45 #ifndef RELEASE
+
46 #define RELEASE(x) if (x) { x->Release(); x=NULL; }
+
47 #endif
+
48 
+
49 #ifndef F2DW
+
50 #define F2DW(x) (*(DWORD*)(&x))
+
51 #endif
+
52 
+
53 #ifndef DW2I
+
54 #define DW2I(x) (*(int*)(&x))
+
55 #endif
+
56 
+
57 // +--------------------------------------------------------------------+
+
58 
+
59 typedef HRESULT (WINAPI * LPDDCE)(GUID FAR *, LPVOID *, REFIID , IUnknown FAR *);
+
60 
+
61 static D3DMATRIX identity_matrix = {
+
62  FLOAT(1.0), FLOAT(0.0), FLOAT(0.0), FLOAT(0.0),
+
63  FLOAT(0.0), FLOAT(1.0), FLOAT(0.0), FLOAT(0.0),
+
64  FLOAT(0.0), FLOAT(0.0), FLOAT(1.0), FLOAT(0.0),
+
65  FLOAT(0.0), FLOAT(0.0), FLOAT(0.0), FLOAT(1.0)
+
66 };
+
67 
+
68 // +--------------------------------------------------------------------+
+
69 
+ +
71 
+ +
73 {
+
74 public:
+ +
76  if (!model_clients.contains(model))
+
77  model_clients.append(model);
+
78  }
+
79 
+
80  virtual ~VideoDX9SurfaceData() {
+
81  model_clients.remove(model);
+
82 
+
83  delete vertex_buffer;
+
84  delete index_buffer;
+
85  }
+
86 
+
87  enum { TYPE = 9001 };
+
88  virtual int GetType() const { return TYPE; }
+
89 
+ + + +
93 };
+
94 
+ +
96 {
+
97 public:
+ +
99  virtual ~VideoDX9SegmentData() { }
+
100 
+
101  enum { TYPE = 9002 };
+
102  virtual int GetType() const { return TYPE; }
+
103 
+ + + +
107  int num_tris;
+
108 };
+
109 
+
110 // +--------------------------------------------------------------------+
+
111 
+
112 static int d3dstate_table[] = {
+
113  D3DRS_FILLMODE, // FILL_MODE
+
114  D3DRS_SHADEMODE, // SHADE_MODE
+
115  D3DRS_LIGHTING, // LIGHTING_ENABLE
+
116  D3DRS_ZENABLE, // Z_ENABLE
+
117  D3DRS_ZWRITEENABLE, // Z_WRITE_ENABLE
+
118  D3DRS_DEPTHBIAS, // Z_BIAS
+
119  0, // TEXTURE_FILTER
+
120  D3DRS_DITHERENABLE, // DITHER_ENABLE
+
121  D3DRS_SPECULARENABLE, // SPECULAR_ENABLE
+
122  D3DRS_FOGENABLE, // FOG_ENABLE
+
123  D3DRS_FOGCOLOR, // FOG_COLOR
+
124  D3DRS_FOGDENSITY, // FOG_DENSITY
+
125  D3DRS_STENCILENABLE, // STENCIL_ENABLE
+
126  0x11111111, // TEXTURE_WRAP (special case)
+
127  0 // LIGHTING_PASS
+
128 };
+
129 
+
130 static const int NUM_SCREEN_VERTS = 1024;
+
131 static const int NUM_SCREEN_INDICES = NUM_SCREEN_VERTS * 2;
+
132 
+
133 // +--------------------------------------------------------------------+
+
134 
+ +
136 {
+
137  FLOAT sx, sy, sz, rhw;
+
138  DWORD diffuse;
+
139  FLOAT tu, tv;
+
140 
+
141  static DWORD FVF;
+
142 };
+
143 
+
144 DWORD VideoDX9ScreenVertex::FVF = D3DFVF_XYZRHW |
+
145 D3DFVF_DIFFUSE |
+
146 D3DFVF_TEX1;
+
147 
+ +
149 {
+
150  FLOAT x, y, z;
+
151  FLOAT nx, ny, nz;
+
152  FLOAT t0u, t0v;
+
153  FLOAT t1u, t1v;
+
154  FLOAT tx, ty, tz;
+
155  FLOAT bx, by, bz;
+
156 
+
157  static DWORD FVF;
+
158 };
+
159 
+
160 DWORD VideoDX9NormalVertex::FVF = 0;
+
161 
+
162 // Global Vertex Declaration shared by shaders
+
163 D3DVERTEXELEMENT9 videoDX9NormalVertexElements[] =
+
164 {
+
165  { 0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 },
+
166  { 0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0 },
+
167  { 0, 24, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0 },
+
168  { 0, 32, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1 },
+
169  { 0, 40, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TANGENT, 2 },
+
170  { 0, 52, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BINORMAL, 3 },
+
171  D3DDECL_END()
+
172 };
+
173 
+ +
175 {
+
176  FLOAT x, y, z;
+
177  FLOAT nx, ny, nz;
+
178  FLOAT tu, tv;
+
179 
+
180  static DWORD FVF;
+
181 };
+
182 
+
183 DWORD VideoDX9SolidVertex::FVF = D3DFVF_XYZ |
+
184 D3DFVF_NORMAL |
+
185 D3DFVF_TEX1 |
+
186 D3DFVF_TEXCOORDSIZE2(0);
+
187 
+ +
189 {
+
190  FLOAT x, y, z;
+
191  DWORD diffuse;
+
192  FLOAT tu, tv;
+
193 
+
194  static DWORD FVF;
+
195 };
+
196 
+
197 DWORD VideoDX9LuminousVertex::FVF = D3DFVF_XYZ |
+
198 D3DFVF_DIFFUSE |
+
199 D3DFVF_TEX1 |
+
200 D3DFVF_TEXCOORDSIZE2(0);
+
201 
+ +
203 {
+
204  FLOAT x, y, z;
+
205  DWORD diffuse;
+
206  DWORD specular;
+
207  FLOAT tu, tv;
+
208  FLOAT tu1, tv1;
+
209 
+
210  static DWORD FVF;
+
211 };
+
212 
+
213 DWORD VideoDX9DetailVertex::FVF = D3DFVF_XYZ |
+
214 D3DFVF_DIFFUSE |
+
215 D3DFVF_SPECULAR |
+
216 D3DFVF_TEX2;
+
217 
+ +
219 {
+
220  FLOAT x, y, z;
+
221  DWORD diffuse;
+
222 
+
223  static DWORD FVF;
+
224 };
+
225 
+
226 DWORD VideoDX9LineVertex::FVF = D3DFVF_XYZ |
+
227 D3DFVF_DIFFUSE;
+
228 
+
229 enum {
+ + + + + + + + +
238 };
+
239 
+
240 // +--------------------------------------------------------------------+
+
241 
+
242 static VideoDX9* video_dx9_instance = 0;
+
243 
+
244 VideoDX9::VideoDX9(const HWND& window, VideoSettings* vs)
+
245 : width(0), height(0), bpp(0), hwnd(window), surface(0),
+
246 d3d(0), d3ddevice(0), device_lost(false), fade(0),
+
247 zdepth(0), gamma(128), num_verts(0), first_vert(0),
+
248 current_texture(0), screen_vbuf(0), screen_ibuf(0),
+
249 font_verts(0), font_indices(0), font_nverts(0),
+
250 nlights(0), use_material(0), d3dx_font(0),
+
251 segment_material(0), strategy(0), passes(0),
+
252 screen_line_verts(0), line_verts(0),
+
253 vertex_declaration(0),
+
254 magic_fx(0), magic_fx_code(0), magic_fx_code_len(0)
+
255 {
+
256  video_dx9_instance = this;
+
257 
+
258  Print("\n********************************\n");
+
259  Print("* Direct 3D version 9 *\n");
+
260  Print("********************************\n\n");
+
261 
+
262  status = VIDEO_ERR;
+
263  HRESULT err = E_OUTOFMEMORY;
+
264 
+
265  d3d = Direct3DCreate9(D3D_SDK_VERSION);
+
266  dx9enum = new(__FILE__,__LINE__) VideoDX9Enum(d3d);
+
267 
+
268  if (d3d && dx9enum) {
+
269  if (vs) {
+
270  dx9enum->req_fullscreen = vs->is_windowed ? false : true;
+
271  dx9enum->req_windowed = vs->is_windowed ? true : false;
+
272  dx9enum->min_stencil_bits = vs->shadows ? 8 : 0;
+
273  dx9enum->uses_depth_buffer = true;
+
274  }
+
275  else {
+
276  dx9enum->req_fullscreen = video_settings.is_windowed ? false : true;
+
277  dx9enum->req_windowed = video_settings.is_windowed ? true : false;
+
278  dx9enum->min_stencil_bits = video_settings.shadows ? 8 : 0;
+
279  dx9enum->uses_depth_buffer = true;
+
280  }
+
281 
+
282  err = dx9enum->Enumerate();
+
283 
+
284  if (FAILED(err)) {
+
285  VideoDX9Error("(ctor) could not enumerate dx9 properties", err);
+
286  delete dx9enum;
+
287  return;
+
288  }
+
289  }
+
290  else {
+
291  VideoDX9Error("(ctor) could not create enumerator", err);
+
292  return;
+
293  }
+
294 
+
295  SetVideoSettings(vs);
+
296 
+
297  if (video_settings.is_windowed)
+
298  dx9enum->SuggestWindowSettings(&video_settings);
+
299  else
+
300  dx9enum->SuggestFullscreenSettings(&video_settings);
+
301 
+
302  SetupParams();
+
303 
+
304  if (VD3D_describe_things > 2) {
+
305  Print("\nD3DPRESENT_PARAMETERS:\n");
+
306  Print(" BackBufferWidth: %d\n", d3dparams.BackBufferWidth);
+
307  Print(" BackBufferHeight: %d\n", d3dparams.BackBufferHeight);
+
308  Print(" BackBufferCount: %d\n", d3dparams.BackBufferCount);
+
309  Print(" BackBufferFormat: %s\n", VideoDX9DisplayMode::D3DFormatToString(d3dparams.BackBufferFormat));
+
310  Print(" Multisample Type: %d\n", d3dparams.MultiSampleType);
+
311  Print(" Multisample Qual: %d\n", d3dparams.MultiSampleQuality);
+
312  Print(" Swap Effect: %d\n", d3dparams.SwapEffect);
+
313  Print(" Device Window: %08X\n", d3dparams.hDeviceWindow);
+
314  Print(" Windowed: %s\n", d3dparams.Windowed ? "true" : "false");
+
315  Print(" Enable Depth/Stencil: %s\n", d3dparams.EnableAutoDepthStencil ? "true" : "false");
+
316  Print(" Depth/Stencil Format: %s\n", VideoDX9DisplayMode::D3DFormatToString(d3dparams.AutoDepthStencilFormat));
+
317  Print(" Flags: %08X\n", d3dparams.Flags);
+
318  Print(" Fullscreen Refresh: %d Hz\n", d3dparams.FullScreen_RefreshRateInHz);
+
319 
+
320  switch (d3dparams.PresentationInterval) {
+
321  case D3DPRESENT_INTERVAL_IMMEDIATE:
+
322  Print(" Present Interval: IMMEDIATE\n");
+
323  break;
+
324 
+
325  case D3DPRESENT_INTERVAL_DEFAULT:
+
326  Print(" Present Interval: DEFAULT\n");
+
327  break;
+
328 
+
329  case D3DPRESENT_INTERVAL_ONE:
+
330  Print(" Present Interval: ONE\n");
+
331  break;
+
332 
+
333  case D3DPRESENT_INTERVAL_TWO:
+
334  Print(" Present Interval: TWO\n");
+
335  break;
+
336 
+
337  case D3DPRESENT_INTERVAL_THREE:
+
338  Print(" Present Interval: THREE\n");
+
339  break;
+
340 
+
341  case D3DPRESENT_INTERVAL_FOUR:
+
342  Print(" Present Interval: FOUR\n");
+
343  break;
+
344 
+
345  default:
+
346  Print(" Present Interval: Unknown (%d)\n", d3dparams.PresentationInterval);
+
347  break;
+
348  }
+
349 
+
350  Print("\n");
+
351  }
+
352 
+
353  Print(" Creating Video Device for HWND = %08x\n", window);
+
354 
+
355  err = d3d->CreateDevice(D3DADAPTER_DEFAULT,
+
356  D3DDEVTYPE_HAL,
+
357  window,
+
358  D3DCREATE_HARDWARE_VERTEXPROCESSING,
+
359  &d3dparams,
+
360  &d3ddevice);
+
361 
+
362  if (FAILED(err)) {
+
363  VideoDX9Error("(ctor) could not create device", err);
+
364  return;
+
365  }
+
366 
+
367  width = video_settings.GetWidth();
+
368  height = video_settings.GetHeight();
+
369  bpp = video_settings.GetDepth();
+
370 
+
371  shadow_enabled = vs->shadows;
+
372  bump_enabled = vs->bumpmaps;
+
373  spec_enabled = vs->specmaps;
+
374 
+
375  render_state[FILL_MODE] = FILL_SOLID;
+
376  render_state[SHADE_MODE] = SHADE_GOURAUD;
+
377  render_state[Z_ENABLE] = false;
+
378  render_state[Z_WRITE_ENABLE] = false;
+
379  render_state[Z_BIAS] = 0;
+
380  render_state[TEXTURE_FILTER] = FILTER_LINEAR;
+
381  render_state[DITHER_ENABLE] = false;
+
382  render_state[SPECULAR_ENABLE] = true;
+
383  render_state[FOG_ENABLE] = false;
+
384  render_state[FOG_COLOR] = 0;
+
385  render_state[FOG_DENSITY] = 0;
+
386  render_state[STENCIL_ENABLE] = false;
+
387  render_state[TEXTURE_WRAP] = true;
+
388  render_state[LIGHTING_PASS] = 0;
+
389 
+
390  ZeroMemory(&rect, sizeof(rect));
+
391 
+
392  if (!texcache)
+
393  texcache = new(__FILE__,__LINE__) TexCacheDX9(this);
+
394 
+
395  if (texcache)
+
396  texcache->count++;
+
397 
+
398  if (VD3D_describe_things > 0) {
+
399  DWORD vmf = VidMemFree() / (1024 * 1024);
+
400  Print(" Available Texture Memory: %d MB\n\n", vmf);
+
401  }
+
402 
+
403  if (CreateBuffers()) {
+
404  d3ddevice->SetRenderState(D3DRS_ALPHATESTENABLE, false);
+
405  d3ddevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESSEQUAL);
+
406 
+
407  d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
+
408  d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
+
409  d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);
+
410  d3ddevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
+
411  d3ddevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
+
412  d3ddevice->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_NONE);
+
413 
+
414  status = VIDEO_OK;
+
415  }
+
416 
+
417  ZeroMemory(font_name, 64);
+
418  font_size = 0;
+
419  font_bold = false;
+
420  font_ital = false;
+
421 }
+
422 
+
423 // +--------------------------------------------------------------------+
+
424 
+ +
426 {
+
427  DestroyBuffers();
+
428 
+
429  texcache->count--;
+
430  if (!texcache->count) {
+
431  delete texcache;
+
432  texcache = 0;
+
433  }
+
434 
+
435  delete environment_cube;
+
436  delete dx9enum;
+
437 
+
438  RELEASE(d3dx_font);
+
439  RELEASE(d3ddevice);
+
440  RELEASE(d3d);
+
441 
+
442  if (magic_fx_code)
+
443  delete [] magic_fx_code;
+
444 
+
445  Print(" VideoDX9: shutdown\n");
+
446  video_dx9_instance = 0;
+
447 }
+
448 
+
449 IDirect3DDevice9*
+ +
451 {
+
452  if (video_dx9_instance)
+
453  return video_dx9_instance->d3ddevice;
+
454 
+
455  return 0;
+
456 }
+
457 
+
458 // +--------------------------------------------------------------------+
+
459 
+
460 bool
+ +
462 {
+
463  if (!dx9enum || dx9enum->NumAdapters() < 1) {
+
464  status = VIDEO_ERR;
+
465  return false;
+
466  }
+
467 
+
468  int adapter_index = video_settings.GetAdapterIndex();
+
469 
+
470  if (adapter_index < 0 || adapter_index >= dx9enum->NumAdapters()) {
+
471  ::Print("WARNING: VideoDX9 could not select adapter %d (max=%d)\n",
+
472  adapter_index, dx9enum->NumAdapters());
+
473 
+
474  adapter_index = 0;
+
475  }
+
476 
+
477  dx9enum->SelectAdapter(adapter_index);
+
478 
+
479  d3dparams.Windowed = video_settings.IsWindowed();
+
480  d3dparams.BackBufferCount = 2;
+
481  d3dparams.MultiSampleType = D3DMULTISAMPLE_NONE;
+
482  d3dparams.MultiSampleQuality = 0;
+
483  d3dparams.SwapEffect = D3DSWAPEFFECT_DISCARD;
+
484  d3dparams.EnableAutoDepthStencil = dx9enum->uses_depth_buffer;
+
485  d3dparams.hDeviceWindow = hwnd;
+
486 
+
487  if (dx9enum->uses_depth_buffer) {
+
488  d3dparams.Flags = D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL;
+
489  d3dparams.AutoDepthStencilFormat = (D3DFORMAT) video_settings.GetDepthStencilFormat();
+
490  }
+
491  else {
+
492  d3dparams.Flags = 0;
+
493  }
+
494 
+
495  d3dparams.Flags |= D3DPRESENTFLAG_DEVICECLIP;
+
496 
+
497  if (video_settings.IsWindowed()) {
+
498  d3dparams.BackBufferWidth = video_settings.window_width;
+
499  d3dparams.BackBufferHeight = video_settings.window_height;
+
500  d3dparams.BackBufferFormat = (D3DFORMAT) video_settings.GetBackBufferFormat();
+
501  d3dparams.FullScreen_RefreshRateInHz = 0;
+
502  d3dparams.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
+
503  }
+
504  else {
+
505  d3dparams.BackBufferWidth = video_settings.GetWidth();
+
506  d3dparams.BackBufferHeight = video_settings.GetHeight();
+
507  d3dparams.BackBufferFormat = (D3DFORMAT) video_settings.GetBackBufferFormat();
+
508  d3dparams.FullScreen_RefreshRateInHz = video_settings.GetRefreshRate();
+
509  d3dparams.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
+
510  }
+
511 
+
512  return true;
+
513 }
+
514 
+
515 
+
516 bool
+
517 VideoDX9::IsModeSupported(int w, int h, int b) const
+
518 {
+
519  if (dx9enum)
+
520  return dx9enum->IsModeSupported(w, h, b);
+
521 
+
522  return false;
+
523 }
+
524 
+
525 bool
+ +
527 {
+
528  // custom video settings:
+
529  if (vs) {
+
530  if (vs != &video_settings)
+
531  CopyMemory(&video_settings, vs, sizeof(VideoSettings));
+
532  }
+
533 
+
534  // default video settings:
+
535  else {
+
536  ZeroMemory(&video_settings, sizeof(VideoSettings));
+
537 
+
538  video_settings.fullscreen_mode.width = 800;
+
539  video_settings.fullscreen_mode.height = 600;
+ +
541  }
+
542 
+
543  return true;
+
544 }
+
545 
+
546 bool
+ +
548 {
+
549  if (!d3ddevice || !SetVideoSettings(vs)) {
+
550  status = VIDEO_ERR;
+
551  return false;
+
552  }
+
553 
+
554  bool using_x_font = (d3dx_font != 0);
+
555 
+
556  RELEASE(d3dx_font);
+
557  InvalidateCache();
+
558  DestroyBuffers();
+
559  SetupParams();
+
560 
+
561  HRESULT hr = d3ddevice->Reset(&d3dparams);
+
562 
+
563  if (FAILED(hr)) {
+
564  VideoDX9Error("could not reset d3d device", hr);
+
565  status = VIDEO_ERR;
+
566  return false;
+
567  }
+
568 
+
569  // Store render target surface desc
+
570  IDirect3DSurface9* back_buffer;
+
571  d3ddevice->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &back_buffer);
+
572  back_buffer->GetDesc(&back_buffer_desc);
+
573  RELEASE(back_buffer);
+
574 
+
575  width = video_settings.GetWidth();
+
576  height = video_settings.GetHeight();
+
577  bpp = video_settings.GetDepth();
+
578 
+
579  shadow_enabled = vs->shadows;
+
580  bump_enabled = vs->bumpmaps;
+
581  spec_enabled = vs->specmaps;
+
582 
+
583 
+
584  if (CreateBuffers()) {
+
585  d3ddevice->SetRenderState(D3DRS_ALPHATESTENABLE, false);
+
586  d3ddevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESSEQUAL);
+
587 
+
588  d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
+
589  d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
+
590  d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);
+
591  d3ddevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
+
592  d3ddevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
+
593  d3ddevice->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_NONE);
+
594 
+
595  D3DVIEWPORT9 view;
+
596 
+
597  hr = d3ddevice->GetViewport(&view);
+
598  if (SUCCEEDED(hr)) {
+
599  rect.x = view.X;
+
600  rect.y = view.Y;
+
601  rect.w = view.Width;
+
602  rect.h = view.Height;
+
603  }
+
604 
+
605  if (using_x_font)
+
606  UseXFont(font_name, font_size, font_bold, font_ital);
+
607 
+
608  status = VIDEO_OK;
+
609  }
+
610 
+
611  return status == VIDEO_OK;
+
612 }
+
613 
+
614 // +--------------------------------------------------------------------+
+
615 
+
616 bool
+
617 VideoDX9::CreateBuffers()
+
618 {
+
619  if (d3ddevice) {
+
620  UINT vertex_size = sizeof(VideoDX9ScreenVertex);
+
621  UINT index_size = sizeof(WORD);
+
622 
+
623  if (!screen_vbuf) {
+
624  screen_vbuf = new(__FILE__,__LINE__) VideoDX9VertexBuffer(
+
625  this,
+
626  NUM_SCREEN_VERTS,
+
627  vertex_size,
+ +
629  D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY);
+
630  }
+
631 
+
632  if (!screen_ibuf) {
+
633  screen_ibuf = new(__FILE__,__LINE__) VideoDX9IndexBuffer(
+
634  this,
+
635  NUM_SCREEN_INDICES,
+
636  D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY);
+
637  }
+
638 
+
639  screen_line_verts = new(__FILE__,__LINE__) VideoDX9ScreenVertex[256];
+
640  line_verts = new(__FILE__,__LINE__) VideoDX9LineVertex[512];
+
641 
+
642  // create effects:
+
643  LPD3DXBUFFER code_buffer = 0;
+
644  DataLoader* loader = DataLoader::GetLoader();
+
645  HRESULT hr = E_FAIL;
+
646 
+
647  hr = d3ddevice->CreateVertexDeclaration(videoDX9NormalVertexElements,
+
648  &vertex_declaration);
+
649 
+
650  // The E - We want to load our shader from the standard filesystem by default, to allow for better modding.
+
651  if (video_settings.use_effects && !magic_fx_code) {
+
652  FILE* f;
+
653  ::fopen_s(&f, "magic.fx", "rb");
+
654 
+
655  if (f) {
+
656  ::fseek(f, 0, SEEK_END);
+
657  magic_fx_code_len = ftell(f);
+
658  ::fseek(f, 0, SEEK_SET);
+
659 
+
660  magic_fx_code = new(__FILE__,__LINE__) BYTE[magic_fx_code_len+1];
+
661  if (magic_fx_code) {
+
662  ::fread(magic_fx_code, magic_fx_code_len, 1, f);
+
663  magic_fx_code[magic_fx_code_len] = 0;
+
664  }
+
665  } else if (loader) {
+
666  magic_fx_code_len = loader->LoadBuffer("magic.fx", magic_fx_code, true, true);
+
667  }
+
668 
+
669  ::fclose(f);
+
670  }
+
671 
+
672  if (video_settings.use_effects && magic_fx_code && magic_fx_code_len) {
+
673  hr = D3DXCreateEffect(d3ddevice,
+
674  magic_fx_code,
+
675  magic_fx_code_len,
+
676  0, 0, 0, 0,
+
677  &magic_fx,
+
678  &code_buffer);
+
679 
+
680  if (code_buffer) {
+
681  ::Print("ERROR - Failed to compile 'magic.fx'\n");
+
682  ::Print((const char*) code_buffer->GetBufferPointer());
+
683  ::Print("\n\n");
+
684  RELEASE(code_buffer);
+
685  }
+
686  }
+
687  }
+
688 
+
689  return screen_vbuf && screen_ibuf;
+
690 }
+
691 
+
692 bool
+
693 VideoDX9::DestroyBuffers()
+
694 {
+
695  if (line_verts) {
+
696  delete line_verts;
+
697  line_verts = 0;
+
698  }
+
699 
+
700  if (screen_line_verts) {
+
701  delete screen_line_verts;
+
702  screen_line_verts = 0;
+
703  }
+
704 
+
705  if (screen_vbuf) {
+
706  delete screen_vbuf;
+
707  screen_vbuf = 0;
+
708  }
+
709 
+
710  if (screen_ibuf) {
+
711  delete screen_ibuf;
+
712  screen_ibuf = 0;
+
713  }
+
714 
+
715  if (font_verts) {
+
716  delete [] font_verts;
+
717  font_verts = 0;
+
718  }
+
719 
+
720  if (font_indices) {
+
721  delete [] font_indices;
+
722  font_indices = 0;
+
723  }
+
724 
+
725  font_nverts = 0;
+
726 
+
727  RELEASE(vertex_declaration);
+
728  RELEASE(magic_fx);
+
729 
+
730  return true;
+
731 }
+
732 
+
733 // +--------------------------------------------------------------------+
+
734 
+
735 DWORD
+ +
737 {
+
738  UINT result = 0;
+
739 
+
740  if (d3ddevice)
+
741  result = d3ddevice->GetAvailableTextureMem();
+
742 
+
743  return result;
+
744 }
+
745 
+
746 int
+ +
748 {
+
749  if (d3d && dx9enum && dx9enum->GetAdapterInfo()) {
+
750  VideoDX9DeviceInfo* dev_info = dx9enum->GetDeviceInfo(video_settings.GetDeviceType());
+
751 
+
752  if (dev_info) {
+
753  return (int) dev_info->caps.MaxTextureWidth;
+
754  }
+
755  }
+
756 
+
757  return 0;
+
758 }
+
759 
+
760 int
+ +
762 {
+
763  if (d3d && dx9enum && dx9enum->GetAdapterInfo()) {
+
764  VideoDX9DeviceInfo* dev_info = dx9enum->GetDeviceInfo(video_settings.GetDeviceType());
+
765 
+
766  if (dev_info) {
+
767  return (int) dev_info->caps.MaxTextureAspectRatio;
+
768  }
+
769  }
+
770 
+
771  return 0;
+
772 }
+
773 
+
774 // +--------------------------------------------------------------------+
+
775 
+
776 void
+ +
778 {
+
779  Print("VideoDX9::RecoverSurfaces()\n");
+
780 
+
781  HRESULT hr = D3D_OK;
+
782 
+
783  surface = 0;
+
784 
+
785  hr = d3ddevice->TestCooperativeLevel();
+
786 
+
787  if (hr == D3DERR_DEVICELOST) {
+
788  // This means that some app took exclusive mode access
+
789  // we need to sit in a loop till we get back to the right mode.
+
790  Print("D3DERR_DEVICELOST\n");
+
791 
+
792  do {
+
793  Sleep(500);
+
794  hr = d3ddevice->TestCooperativeLevel();
+
795  } while (hr == D3DERR_DEVICELOST);
+
796  }
+
797 
+
798  if (hr == D3DERR_DEVICENOTRESET) {
+
799  if (Reset(&video_settings))
+
800  hr = S_OK;
+
801  }
+
802 
+
803  if (SUCCEEDED(hr)) {
+
804  Print("* Invalidating Texture Cache\n");
+
805  // Re-fill the contents of textures which just got restored:
+
806  InvalidateCache();
+
807 
+
808  device_lost = false;
+
809  }
+
810 
+
811  Print("* Vid Mem Free: %8d\n", VidMemFree());
+
812  Print("* Recover Surfaces Complete.\n\n");
+
813 }
+
814 
+
815 // +--------------------------------------------------------------------+
+
816 
+
817 bool
+ +
819 {
+
820  background = c;
+
821  return true;
+
822 }
+
823 
+
824 //-----------------------------------------------------------------------------
+
825 // RampValue
+
826 //
+
827 // The gamma function with inputs in [0,255], scaled to a range with the
+
828 // default range appropriate for D3DGAMMARAMP.
+
829 //
+
830 inline WORD
+
831 RampValue(UINT i, double recip_gamma, double fade)
+
832 {
+
833  return (WORD) (65535.0 * fade * pow((double)i/255.f, recip_gamma));
+
834 }
+
835 
+
836 //-----------------------------------------------------------------------------
+
837 // ReciprocalGamma
+
838 //
+
839 // Given a gamma corrected i in [0,255], return 1/gamma
+
840 //
+
841 inline float
+ +
843 {
+
844  return logf(i/255.f)/logf(0.5f);
+
845 }
+
846 
+
847 //-----------------------------------------------------------------------------
+
848 // GammaValue
+
849 //
+
850 // Given a gamma corrected color channel value in [0,255], return the gamma.
+
851 //
+
852 inline float
+
853 GammaValue(UINT i)
+
854 {
+
855  return logf(0.5f)/logf(i/255.f);
+
856 }
+
857 
+
858 bool
+ +
860 {
+
861  HRESULT hr = E_FAIL;
+
862  double f = Color::GetFade();
+
863 
+
864  if (gamma != g || fade != f) {
+
865  if (d3ddevice) {
+
866  //::Print("VideoDX9 - SetGammaLevel(%d) fade = %f\n", g, f);
+
867 
+
868  // compute 1/gamma
+
869  float recip_gray = ReciprocalGamma(g);
+
870 
+
871  // compute i**(1/gamma) for all i and scale to range
+
872  for (UINT i = 0; i < 256; i++) {
+
873  int val = RampValue(i, recip_gray, f);
+
874 
+
875  gamma_ramp.red[i] = val;
+
876  gamma_ramp.green[i] = val;
+
877  gamma_ramp.blue[i] = val;
+
878  }
+
879 
+
880  d3ddevice->SetGammaRamp(0, D3DSGR_NO_CALIBRATION, &gamma_ramp);
+
881  hr = D3D_OK;
+
882  }
+
883 
+
884  gamma = g;
+
885  fade = f;
+
886  }
+
887 
+
888  return SUCCEEDED(hr);
+
889 }
+
890 
+
891 bool
+
892 VideoDX9::SetObjTransform(const Matrix& orient, const Point& loc)
+
893 {
+
894  HRESULT hr = E_FAIL;
+
895 
+
896  if (d3ddevice) {
+
897  D3DMATRIX world_matrix;
+
898  CreateD3DMatrix(world_matrix, orient, loc);
+
899  hr = d3ddevice->SetTransform(D3DTS_WORLD, &world_matrix);
+
900 
+
901  matrixWorld = world_matrix;
+
902  D3DXMatrixInverse(&matrixWorldInverse, 0, &matrixWorld);
+
903  }
+
904 
+
905  return SUCCEEDED(hr);
+
906 }
+
907 
+
908 // +--------------------------------------------------------------------+
+
909 
+
910 bool
+ +
912 {
+
913  HRESULT err;
+
914 
+
915  err = d3ddevice->Clear(0,
+
916  NULL,
+
917  D3DCLEAR_TARGET | D3DCLEAR_STENCIL | D3DCLEAR_ZBUFFER,
+
918  background.Value(),
+
919  1.0f,
+
920  0);
+
921 
+
922  if (FAILED(err)) {
+
923  static int report = 10;
+
924  if (report > 0) {
+
925  VideoDX9Error("Failed to clear device", err);
+
926  report--;
+
927  }
+
928  }
+
929 
+
930  return true;
+
931 }
+
932 
+
933 bool
+ +
935 {
+
936  HRESULT err;
+
937 
+
938  err = d3ddevice->Clear(0,
+
939  NULL,
+
940  D3DCLEAR_STENCIL | D3DCLEAR_ZBUFFER,
+
941  0,
+
942  1.0f,
+
943  0);
+
944 
+
945  if (FAILED(err)) {
+
946  static int report = 10;
+
947  if (report > 0) {
+
948  VideoDX9Error("Failed to clear depth buffer", err);
+
949  report--;
+
950  }
+
951  }
+
952 
+
953  return true;
+
954 }
+
955 
+
956 // +--------------------------------------------------------------------+
+
957 
+
958 bool
+ +
960 {
+
961  // Show the frame on the primary surface.
+
962  HRESULT err = d3ddevice->Present( NULL, NULL, NULL, NULL );
+
963 
+
964  if (FAILED(err)) {
+
965  if (err == D3DERR_DEVICELOST) {
+
966  device_lost = true;
+
967  }
+
968 
+
969  else {
+
970  static int report = 10;
+
971  if (report > 0) {
+
972  VideoDX9Error("Could not present frame", err);
+
973  report--;
+
974  }
+
975  }
+
976  }
+
977 
+
978  return true;
+
979 }
+
980 
+
981 // +--------------------------------------------------------------------+
+
982 
+
983 bool
+ +
985 {
+
986  return true;
+
987 }
+
988 
+
989 // +--------------------------------------------------------------------+
+
990 
+
991 bool
+ +
993 {
+
994  return true;
+
995 }
+
996 
+
997 // +--------------------------------------------------------------------+
+
998 
+
999 void
+ +
1001 {
+
1002  if (s)
+
1003  PrepareSurface(s);
+
1004 }
+
1005 
+
1006 void
+ +
1008 {
+
1009  if (texcache && tex)
+
1010  texcache->FindTexture(tex);
+
1011 }
+
1012 
+
1013 void
+ +
1015 {
+ +
1017  while (++iter) {
+
1018  // remove each model from the list...
+
1019  Model* model = iter.removeItem();
+
1020 
+
1021  // ...so that the buffer destructor doesn't
+
1022  // do it and mess up the iterator.
+
1023  model->DeletePrivateData();
+
1024  }
+
1025 
+
1026  if (texcache)
+
1027  texcache->InvalidateCache();
+
1028 }
+
1029 
+
1030 // +--------------------------------------------------------------------+
+
1031 
+
1032 void
+
1033 VideoDX9::CreateD3DMatrix(D3DMATRIX& result, const Matrix& m, const Point& p)
+
1034 {
+
1035  result._11 = (float) m.elem[0][0];
+
1036  result._12 = (float) m.elem[1][0];
+
1037  result._13 = (float) m.elem[2][0];
+
1038  result._14 = 0.0f;
+
1039 
+
1040  result._21 = (float) m.elem[0][1];
+
1041  result._22 = (float) m.elem[1][1];
+
1042  result._23 = (float) m.elem[2][1];
+
1043  result._24 = 0.0f;
+
1044 
+
1045  result._31 = (float) m.elem[0][2];
+
1046  result._32 = (float) m.elem[1][2];
+
1047  result._33 = (float) m.elem[2][2];
+
1048  result._34 = 0.0f;
+
1049 
+
1050  result._41 = (float) p.x;
+
1051  result._42 = (float) p.y;
+
1052  result._43 = (float) p.z;
+
1053  result._44 = 1.0f;
+
1054 }
+
1055 
+
1056 void
+
1057 VideoDX9::CreateD3DMatrix(D3DMATRIX& result, const Matrix& m, const Vec3& v)
+
1058 {
+
1059  result._11 = (float) m.elem[0][0];
+
1060  result._12 = (float) m.elem[1][0];
+
1061  result._13 = (float) m.elem[2][0];
+
1062  result._14 = 0.0f;
+
1063 
+
1064  result._21 = (float) m.elem[0][1];
+
1065  result._22 = (float) m.elem[1][1];
+
1066  result._23 = (float) m.elem[2][1];
+
1067  result._24 = 0.0f;
+
1068 
+
1069  result._31 = (float) m.elem[0][2];
+
1070  result._32 = (float) m.elem[1][2];
+
1071  result._33 = (float) m.elem[2][2];
+
1072  result._34 = 0.0f;
+
1073 
+
1074  result._41 = v.x;
+
1075  result._42 = v.y;
+
1076  result._43 = v.z;
+
1077  result._44 = 1.0f;
+
1078 }
+
1079 
+
1080 void
+
1081 VideoDX9::CreateD3DMaterial(D3DMATERIAL9& result, const Material& mtl)
+
1082 {
+
1083  CopyMemory(&result.Diffuse, &mtl.Kd, sizeof(D3DCOLORVALUE));
+
1084  CopyMemory(&result.Ambient, &mtl.Ka, sizeof(D3DCOLORVALUE));
+
1085  CopyMemory(&result.Specular, &mtl.Ks, sizeof(D3DCOLORVALUE));
+
1086  CopyMemory(&result.Emissive, &mtl.Ke, sizeof(D3DCOLORVALUE));
+
1087 
+
1088  result.Power = mtl.power;
+
1089 }
+
1090 
+
1091 
+
1092 // +--------------------------------------------------------------------+
+
1093 
+
1094 bool
+ +
1096 {
+
1097  if (d3ddevice) {
+
1098  HRESULT hr = E_FAIL;
+
1099  LPDIRECT3DSURFACE9 pSurf=NULL, pTempSurf=NULL;
+
1100  D3DSURFACE_DESC desc;
+
1101  D3DDISPLAYMODE dm;
+
1102 
+
1103  // get display dimensions
+
1104  // this will be the dimensions of the front buffer
+
1105  hr = d3ddevice->GetDisplayMode(0, &dm);
+
1106 
+
1107  if (FAILED(hr))
+
1108  VideoDX9Error("VideoDX9::Capture - Can't get display mode!", hr);
+
1109 
+
1110  desc.Width = dm.Width;
+
1111  desc.Height = dm.Height;
+
1112  desc.Format = D3DFMT_A8R8G8B8;
+
1113 
+
1114  hr = d3ddevice->CreateOffscreenPlainSurface(
+
1115  desc.Width,
+
1116  desc.Height,
+
1117  desc.Format,
+
1118  D3DPOOL_SYSTEMMEM,
+
1119  &pTempSurf,
+
1120  NULL);
+
1121 
+
1122  if (FAILED(hr)) {
+
1123  VideoDX9Error("VideoDX9::Capture - Cannot create offscreen buffer 1", hr);
+
1124  return false;
+
1125  }
+
1126 
+
1127  hr = d3ddevice->GetFrontBufferData(0, pTempSurf);
+
1128 
+
1129  if (FAILED(hr)) {
+
1130  RELEASE(pTempSurf);
+
1131  VideoDX9Error("VideoDX9::Capture - Can't get front buffer", hr);
+
1132  return false;
+
1133  }
+
1134 
+
1135 
+
1136  if (video_settings.IsWindowed()) {
+
1137  POINT pt={0, 0};
+
1138  RECT srcRect;
+
1139 
+
1140  // capture only the client area of the screen:
+
1141  ::GetClientRect(hwnd, &srcRect);
+
1142  ::ClientToScreen(hwnd, (LPPOINT) &srcRect);
+
1143  srcRect.right += srcRect.left;
+
1144  srcRect.bottom += srcRect.top;
+
1145 
+
1146  desc.Width = srcRect.right - srcRect.left;
+
1147  desc.Height = srcRect.bottom - srcRect.top;
+
1148  desc.Format = D3DFMT_A8R8G8B8; // this is what we get from the screen, so stick with it
+
1149 
+
1150  // NB we can't lock the back buffer direct because it's no created that way
+
1151  // and to do so hits performance, so copy to another surface
+
1152  // Must be the same format as the source surface
+
1153  hr = d3ddevice->CreateOffscreenPlainSurface(
+
1154  desc.Width,
+
1155  desc.Height,
+
1156  desc.Format,
+
1157  D3DPOOL_DEFAULT,
+
1158  &pSurf,
+
1159  NULL);
+
1160 
+
1161  if (FAILED(hr)) {
+
1162  RELEASE(pSurf);
+
1163  VideoDX9Error("VideoDX9::Capture - Cannot create offscreen buffer 2", hr);
+
1164  return false;
+
1165  }
+
1166 
+
1167  // Copy
+
1168  hr = d3ddevice->UpdateSurface(pTempSurf, &srcRect, pSurf, &pt);
+
1169 
+
1170  if (FAILED(hr)) {
+
1171  RELEASE(pTempSurf);
+
1172  RELEASE(pSurf);
+
1173  VideoDX9Error("VideoDX9::Capture - Cannot update surface", hr);
+
1174  return false;
+
1175  }
+
1176 
+
1177  RELEASE(pTempSurf);
+
1178  pTempSurf = pSurf;
+
1179  pSurf = NULL;
+
1180  }
+
1181 
+
1182  D3DLOCKED_RECT lockedRect;
+
1183  hr = pTempSurf->LockRect(&lockedRect, NULL,
+
1184  D3DLOCK_READONLY | D3DLOCK_NOSYSLOCK);
+
1185 
+
1186  if (FAILED(hr)) {
+
1187  VideoDX9Error("VideoDX9::Capture - can't lock rect", hr);
+
1188  RELEASE(pTempSurf);
+
1189  return false;
+
1190  }
+
1191 
+
1192  // Allocate color buffer
+
1193  DWORD* buffer = new DWORD[desc.Width * desc.Height];
+
1194  BYTE* src = (BYTE*) lockedRect.pBits;
+
1195  BYTE* dst = (BYTE*) buffer;
+
1196  Color clr;
+
1197 
+
1198  for (DWORD y = 0; y < desc.Height; y++) {
+
1199  BYTE *pRow = src;
+
1200 
+
1201  for (DWORD x = 0; x < desc.Width; x++) {
+
1202  switch(desc.Format) {
+
1203  case D3DFMT_R5G6B5:
+
1204  clr = Color::Unformat(*((WORD*) (pRow)));
+
1205 
+
1206  *dst++ = (BYTE) clr.Red();
+
1207  *dst++ = (BYTE) clr.Green();
+
1208  *dst++ = (BYTE) clr.Blue();
+
1209  *dst++ = 255;
+
1210  break;
+
1211 
+
1212  case D3DFMT_A8R8G8B8:
+
1213  case D3DFMT_X8R8G8B8:
+
1214  *dst++ = pRow[0]; // R
+
1215  *dst++ = pRow[1]; // G
+
1216  *dst++ = pRow[2]; // B
+
1217  *dst++ = 255;
+
1218 
+
1219  pRow += 4;
+
1220  break;
+
1221 
+
1222  case D3DFMT_R8G8B8:
+
1223  *dst++ = pRow[0]; // R
+
1224  *dst++ = pRow[1]; // G
+
1225  *dst++ = pRow[2]; // B
+
1226  *dst++ = 255;
+
1227 
+
1228  pRow += 3;
+
1229  break;
+
1230  }
+
1231 
+
1232  }
+
1233 
+
1234  src += lockedRect.Pitch;
+
1235  }
+
1236 
+
1237  bmp.CopyHighColorImage(desc.Width, desc.Height, buffer);
+
1238 
+
1239  delete [] buffer;
+
1240 
+
1241  RELEASE(pTempSurf);
+
1242  RELEASE(pSurf);
+
1243 
+
1244  return SUCCEEDED(hr);
+
1245  }
+
1246 
+
1247  return false;
+
1248 }
+
1249 
+
1250 // +--------------------------------------------------------------------+
+
1251 
+
1252 bool
+ +
1254 {
+
1255  if (d3ddevice && (rect.w < 1 || rect.h < 1)) {
+
1256  D3DVIEWPORT9 view;
+
1257  HRESULT hr = d3ddevice->GetViewport(&view);
+
1258  if (SUCCEEDED(hr)) {
+
1259  rect.x = view.X;
+
1260  rect.y = view.Y;
+
1261  rect.w = view.Width;
+
1262  rect.h = view.Height;
+
1263  }
+
1264  }
+
1265 
+
1266  r = rect;
+
1267  return true;
+
1268 }
+
1269 
+
1270 // +--------------------------------------------------------------------+
+
1271 
+
1272 bool
+ +
1274 {
+
1275  return SetViewport(r.x, r.y, r.w, r.h);
+
1276 }
+
1277 
+
1278 // +--------------------------------------------------------------------+
+
1279 
+
1280 bool
+
1281 VideoDX9::SetViewport(int x, int y, int w, int h)
+
1282 {
+
1283  if (!d3d || !d3ddevice)
+
1284  return false;
+
1285 
+
1286  HRESULT hr;
+
1287 
+
1288  // set up the viewport according to args:
+
1289  D3DVIEWPORT9 view;
+
1290 
+
1291  view.X = x;
+
1292  view.Y = y;
+
1293  view.Width = w;
+
1294  view.Height = h;
+
1295  view.MinZ = 0.0f;
+
1296  view.MaxZ = 1.0f;
+
1297 
+
1298  hr = d3ddevice->SetViewport(&view);
+
1299  if (FAILED(hr)) {
+
1300  VideoDX9Error("could not initialize viewport", hr);
+
1301  return false;
+
1302  }
+
1303 
+
1304  // set up the render state:
+
1305  for (int i = FILL_MODE; i < TEXTURE_WRAP; i++) {
+
1306  if (d3dstate_table[i]) {
+
1307  d3ddevice->SetRenderState((D3DRENDERSTATETYPE) d3dstate_table[i], render_state[i]);
+
1308  }
+
1309  }
+
1310 
+
1311  d3ddevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESSEQUAL);
+
1312 
+
1313  rect.x = x;
+
1314  rect.y = y;
+
1315  rect.w = w;
+
1316  rect.h = h;
+
1317 
+
1318  return true;
+
1319 }
+
1320 
+
1321 // +--------------------------------------------------------------------+
+
1322 
+
1323 bool
+ +
1325 {
+
1326  ambient = c;
+
1327  return true;
+
1328 }
+
1329 
+
1330 bool
+ +
1332 {
+
1333  if (d3ddevice) {
+
1334  main_light = 0;
+
1335  back_light = 0;
+
1336 
+
1337  ListIter<Light> iter = (List<Light>&) lights;
+
1338  int index = -1;
+
1339 
+
1340  while (++iter) {
+
1341  Light* light = iter.value();
+
1342 
+
1343  if (light->IsActive()) {
+
1344  D3DLIGHT9 d3d_light;
+
1345  ZeroMemory(&d3d_light, sizeof(d3d_light));
+
1346  d3d_light.Type = (D3DLIGHTTYPE) light->Type();
+
1347 
+
1348  if (light->Type() == Light::LIGHT_DIRECTIONAL) {
+
1349  d3d_light.Direction.x = (float) (-light->Location().x);
+
1350  d3d_light.Direction.y = (float) (-light->Location().y);
+
1351  d3d_light.Direction.z = (float) (-light->Location().z);
+
1352 
+
1353  if (d3d_light.Direction.x == 0 &&
+
1354  d3d_light.Direction.y == 0 &&
+
1355  d3d_light.Direction.z == 0) {
+
1356 
+
1357  d3d_light.Direction.y = -1;
+
1358  }
+
1359 
+
1360  if (light->CastsShadow()) {
+
1361  if (!main_light || light->Intensity() > main_light->Intensity())
+
1362  main_light = light;
+
1363  }
+
1364  else if (!back_light) {
+
1365  back_light = light;
+
1366  }
+
1367  }
+
1368  else {
+
1369  d3d_light.Position.x = (float) ( light->Location().x);
+
1370  d3d_light.Position.y = (float) ( light->Location().y);
+
1371  d3d_light.Position.z = (float) ( light->Location().z);
+
1372  }
+
1373 
+
1374  float r = (light->GetColor().Red() / 255.0f) * light->Intensity();
+
1375  float g = (light->GetColor().Green() / 255.0f) * light->Intensity();
+
1376  float b = (light->GetColor().Blue() / 255.0f) * light->Intensity();
+
1377 
+
1378  d3d_light.Diffuse.r = r;
+
1379  d3d_light.Diffuse.g = g;
+
1380  d3d_light.Diffuse.b = b;
+
1381 
+
1382  d3d_light.Specular.r = r;
+
1383  d3d_light.Specular.g = g;
+
1384  d3d_light.Specular.b = b;
+
1385 
+
1386  d3d_light.Range = light->Intensity() * 10.0f;
+
1387  d3d_light.Attenuation0 = 0.1f;
+
1388  d3d_light.Attenuation1 = 0.7f;
+
1389  d3d_light.Attenuation2 = 0.0f;
+
1390 
+
1391  index++;
+
1392  d3ddevice->SetLight(index, &d3d_light);
+
1393  d3ddevice->LightEnable(index, TRUE);
+
1394  }
+
1395  }
+
1396 
+
1397  // turn off any unused lights from before:
+
1398  while (nlights > index+1) {
+
1399  d3ddevice->LightEnable(--nlights, FALSE);
+
1400  }
+
1401 
+
1402  nlights = index + 1;
+
1403 
+
1404  return true;
+
1405  }
+
1406 
+
1407  return false;
+
1408 }
+
1409 
+
1410 bool
+ +
1412 {
+
1413  if (d3ddevice) {
+
1414  camera = cam;
+
1415 
+
1416  D3DMATRIX m;
+
1417  CreateD3DMatrix(m, cam->Orientation(), cam->Pos());
+
1418  d3ddevice->SetTransform(D3DTS_VIEW, &m);
+
1419  matrixView = m;
+
1420 
+
1421  return true;
+
1422  }
+
1423 
+
1424  return false;
+
1425 }
+
1426 
+
1427 bool
+
1428 VideoDX9::SetProjection(float fov, float znear, float zfar, DWORD type)
+
1429 {
+
1430  if (d3ddevice && zfar > znear) {
+
1431  D3DMATRIX m;
+
1432  float h, w, Q;
+
1433 
+
1434  double width = (float) (rect.w);
+
1435  double height = (float) (rect.h);
+
1436  ZeroMemory(&m, sizeof(m));
+
1437 
+
1438  /***
+
1439  *** PERSPECTIVE PROJECTION:
+
1440  ***/
+
1441 
+
1442  if (type == PROJECTION_PERSPECTIVE) {
+
1443  double xscale = width / fov;
+
1444  double yscale = height / fov;
+
1445 
+
1446  double maxscale = xscale;
+
1447  if (yscale > xscale) maxscale = yscale;
+
1448 
+
1449  double xangle = atan(fov/2 * maxscale/xscale);
+
1450 
+
1451  w = (float) (2/tan(xangle)); // 1/tan(x) == cot(x)
+
1452  h = (float) (w * width/height);
+
1453  Q = zfar/(zfar - znear);
+
1454 
+
1455  m._11 = w;
+
1456  m._22 = h;
+
1457  m._33 = Q;
+
1458  m._43 = -Q*znear;
+
1459  m._34 = 1;
+
1460  }
+
1461 
+
1462  /***
+
1463  *** ORTHOGONAL PROJECTION:
+
1464  ***/
+
1465 
+
1466  else if (type == PROJECTION_ORTHOGONAL) {
+
1467  m._11 = (float) (fov/width);
+
1468  m._22 = (float) (fov/height);
+
1469  m._33 = (float) (1/(zfar-znear));
+
1470  m._43 = (float) (znear/(znear-zfar));
+
1471  m._44 = (float) (1);
+
1472  }
+
1473 
+
1474  else {
+
1475  return false;
+
1476  }
+
1477 
+
1478  d3ddevice->SetTransform(D3DTS_PROJECTION, &m);
+
1479  matrixProj = m;
+
1480 
+
1481  return true;
+
1482  }
+
1483 
+
1484  return false;
+
1485 }
+
1486 
+
1487 // +--------------------------------------------------------------------+
+
1488 
+
1489 bool
+ +
1491 {
+
1492  if (environment_cube && !faces) {
+
1493  delete environment_cube;
+
1494  environment_cube = 0;
+
1495  return true;
+
1496  }
+
1497 
+
1498  if (!environment_cube) {
+
1499  environment_cube = new(__FILE__,__LINE__) TexCubeDX9(this);
+
1500  }
+
1501 
+
1502  if (environment_cube) {
+
1503  bool ok = true;
+
1504  for (int i = 0; i < 6; i++)
+
1505  ok = ok && environment_cube->LoadTexture(faces[i], i);
+
1506  return ok;
+
1507  }
+
1508 
+
1509  return false;
+
1510 }
+
1511 
+
1512 // +--------------------------------------------------------------------+
+
1513 
+
1514 bool
+ +
1516 {
+
1517  if (!d3ddevice)
+
1518  return false;
+
1519 
+
1520  if (render_state[state] == value || d3dstate_table[state] == 0) {
+
1521  render_state[state] = value;
+
1522  return true;
+
1523  }
+
1524 
+
1525  HRESULT hr = E_FAIL;
+
1526 
+
1527  // special case for texture wrapping:
+
1528  if (state == TEXTURE_WRAP) {
+
1529  DWORD wrap = D3DTADDRESS_CLAMP;
+
1530 
+
1531  if (value)
+
1532  wrap = D3DTADDRESS_WRAP;
+
1533 
+
1534  hr = d3ddevice->SetSamplerState(0, D3DSAMP_ADDRESSU, wrap);
+
1535  hr = d3ddevice->SetSamplerState(0, D3DSAMP_ADDRESSV, wrap);
+
1536  }
+
1537 
+
1538  // special case for fog enable:
+
1539  else if (state == FOG_ENABLE) {
+
1540  if (value) {
+
1541  hr = d3ddevice->SetRenderState(D3DRS_FOGVERTEXMODE, D3DFOG_EXP);
+
1542  hr = d3ddevice->SetRenderState(D3DRS_FOGTABLEMODE, D3DFOG_NONE);
+
1543  }
+
1544 
+
1545  hr = d3ddevice->SetRenderState(D3DRS_FOGENABLE, value);
+
1546  }
+
1547 
+
1548  // special case for z bias
+
1549  else if (state == Z_BIAS) {
+
1550  if (value) {
+
1551  FLOAT bias_scale = 1.0f;
+
1552  FLOAT depth_bias = (FLOAT) (DW2I(value) / -10000.0);
+
1553 
+
1554  hr = d3ddevice->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, F2DW(bias_scale));
+
1555  hr = d3ddevice->SetRenderState(D3DRS_DEPTHBIAS, F2DW(depth_bias));
+
1556  }
+
1557  else {
+
1558  hr = d3ddevice->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, 0);
+
1559  hr = d3ddevice->SetRenderState(D3DRS_DEPTHBIAS, 0);
+
1560  }
+
1561  }
+
1562 
+
1563  // set default z func along with z enable
+
1564  else if (state == Z_ENABLE) {
+
1565  hr = d3ddevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESSEQUAL);
+
1566  hr = d3ddevice->SetRenderState(D3DRS_ZENABLE, value);
+
1567  }
+
1568 
+
1569  // all other render states:
+
1570  else {
+
1571  hr = d3ddevice->SetRenderState((D3DRENDERSTATETYPE) d3dstate_table[state], value);
+
1572  }
+
1573 
+
1574  if (FAILED(hr)) {
+
1575  VideoDX9Error("could not SetRenderState", hr);
+
1576  return false;
+
1577  }
+
1578  else {
+
1579  render_state[state] = value;
+
1580  }
+
1581 
+
1582  return true;
+
1583 }
+
1584 
+
1585 bool
+
1586 VideoDX9::SetBlendType(int blend_type)
+
1587 {
+
1588  if (blend_type == current_blend_state)
+
1589  return true;
+
1590 
+
1591  switch (blend_type) {
+
1592  default:
+
1593  // map misc blend types to SOLID
+
1594  // and fall through to that case
+
1595 
+
1596  blend_type = BLEND_SOLID;
+
1597 
+
1598  case BLEND_SOLID:
+
1599  d3ddevice->SetRenderState(D3DRS_ALPHABLENDENABLE, false);
+
1600  break;
+
1601 
+
1602  case BLEND_ALPHA:
+
1603  d3ddevice->SetRenderState(D3DRS_ALPHABLENDENABLE, true);
+
1604  d3ddevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
+
1605  d3ddevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
+
1606  break;
+
1607 
+
1608  case BLEND_ADDITIVE:
+
1609  d3ddevice->SetRenderState(D3DRS_ALPHABLENDENABLE, true);
+
1610  d3ddevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
+
1611  d3ddevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
+
1612  break;
+
1613  }
+
1614 
+
1615  current_blend_state = blend_type;
+
1616  return true;
+
1617 }
+
1618 
+
1619 // +--------------------------------------------------------------------+
+
1620 
+
1621 bool
+ +
1623 {
+
1624  if (device_lost) {
+
1625  RecoverSurfaces();
+
1626 
+
1627  if (status != VIDEO_OK)
+
1628  return false;
+
1629  }
+
1630 
+
1631  stats.Clear();
+
1632 
+
1633  HRESULT err = 0;
+
1634  static int frame_number = 1;
+
1635  static int report_errs = 100;
+
1636 
+
1637  stats.nframe = frame_number;
+
1638  texcache->FrameNumber(frame_number++);
+
1639 
+
1640  // update gamma ramp for global fade value:
+
1641  SetGammaLevel(gamma);
+
1642 
+
1643  ClearAll();
+
1644 
+
1645  err = d3ddevice->BeginScene();
+
1646 
+
1647  if (FAILED(err)) {
+
1648  if (report_errs > 0) {
+
1649  report_errs--;
+
1650  VideoDX9Error("could not begin scene", err);
+
1651  }
+
1652 
+
1653  return false;
+
1654  }
+
1655 
+
1656  scene_active = 1;
+
1657  current_blend_state = -1;
+
1658 
+ + +
1661 
+
1662  return true;
+
1663 }
+
1664 
+
1665 // +--------------------------------------------------------------------+
+
1666 
+
1667 bool
+ +
1669 {
+
1670  HRESULT err = 0;
+
1671 
+
1672  if (scene_active) {
+
1673  err = d3ddevice->EndScene();
+
1674 
+
1675  if (FAILED(err)) {
+
1676  VideoDX9Error("could not end scene", err);
+
1677  return false;
+
1678  }
+
1679  }
+
1680 
+
1681  scene_active = 0;
+
1682  return true;
+
1683 }
+
1684 
+
1685 // +--------------------------------------------------------------------+
+
1686 
+
1687 static DWORD ColorModulate(DWORD a, DWORD b)
+
1688 {
+
1689  float a0 = (float) ((a ) & 0xff)/255.0f;
+
1690  float a1 = (float) ((a>> 8) & 0xff)/255.0f;
+
1691  float a2 = (float) ((a>>16) & 0xff)/255.0f;
+
1692  float a3 = (float) ((a>>24) & 0xff)/255.0f;
+
1693 
+
1694  float b0 = (float) ((b ) & 0xff)/255.0f;
+
1695  float b1 = (float) ((b>> 8) & 0xff)/255.0f;
+
1696  float b2 = (float) ((b>>16) & 0xff)/255.0f;
+
1697  float b3 = (float) ((b>>24) & 0xff)/255.0f;
+
1698 
+
1699  return (DWORD) ((BYTE)(a3*b3*255.0f) << 24) |
+
1700  ((BYTE)(a2*b2*255.0f) << 16) |
+
1701  ((BYTE)(a1*b1*255.0f) << 8) |
+
1702  ((BYTE)(a0*b0*255.0f));
+
1703 }
+
1704 
+
1705 // +--------------------------------------------------------------------+
+
1706 
+
1707 bool
+
1708 VideoDX9::PopulateScreenVerts(VertexSet* vset)
+
1709 {
+
1710  if (!vset || !screen_vbuf)
+
1711  return false;
+
1712 
+
1713  num_verts = vset->nverts;
+
1714 
+
1715  VideoDX9ScreenVertex* v = (VideoDX9ScreenVertex*) screen_vbuf->Lock(num_verts);
+
1716 
+
1717  if (v) {
+
1718  first_vert = screen_vbuf->GetNextVert();
+
1719 
+
1720  for (int i = 0; i < num_verts; i++) {
+
1721  v->sx = vset->s_loc[i].x;
+
1722  v->sy = vset->s_loc[i].y;
+
1723  v->sz = vset->s_loc[i].z;
+
1724  v->rhw = vset->rw[i];
+
1725 
+
1726  v->diffuse = vset->diffuse[i];
+
1727 
+
1728  v->tu = vset->tu[i];
+
1729  v->tv = vset->tv[i];
+
1730 
+
1731  v++;
+
1732  }
+
1733 
+
1734  screen_vbuf->Unlock();
+
1735  return true;
+
1736  }
+
1737 
+
1738  Print(" VideoDX9: could not lock screen vbuf for %d verts.\n", num_verts);
+
1739  return false;
+
1740 }
+
1741 
+
1742 // +--------------------------------------------------------------------+
+
1743 
+
1744 bool
+
1745 VideoDX9::DrawPolys(int npolys, Poly* polys)
+
1746 {
+
1747  bool result = false;
+
1748 
+
1749  if (d3ddevice && polys && npolys > 0) {
+
1750  // screen space polys:
+
1751  if (polys->vertex_set->space == VertexSet::SCREEN_SPACE)
+
1752  return DrawScreenPolys(npolys, polys);
+
1753 
+
1754  // world space polys:
+
1755  stats.ncalls++;
+
1756 
+
1757  VertexSet* vset = polys->vertex_set;
+
1758  int nverts = vset->nverts;
+
1759  bool luminous = false;
+
1760  bool detail = false;
+
1761  DWORD fvf = 0;
+
1762  void* verts = 0;
+
1763  int vsize = 0;
+
1764  WORD* indices = new(__FILE__,__LINE__) WORD[npolys*6];
+
1765 
+
1766  if (polys->material) {
+
1767  luminous = polys->material->luminous;
+
1768  }
+
1769 
+
1770  if (vset->tu1 != 0) {
+
1771  VideoDX9DetailVertex* v = new(__FILE__,__LINE__) VideoDX9DetailVertex[nverts];
+
1772  verts = v;
+
1773  vsize = sizeof(VideoDX9DetailVertex);
+ +
1775 
+
1776  for (int i = 0; i < nverts; i++) {
+
1777  v->x = vset->loc[i].x;
+
1778  v->y = vset->loc[i].y;
+
1779  v->z = vset->loc[i].z;
+
1780 
+
1781  v->diffuse = vset->diffuse[i];
+
1782  v->specular = vset->specular[i];
+
1783 
+
1784  v->tu = vset->tu[i];
+
1785  v->tv = vset->tv[i];
+
1786  v->tu1 = vset->tu1[i];
+
1787  v->tv1 = vset->tv1[i];
+
1788 
+
1789  v++;
+
1790  }
+
1791  }
+
1792 
+
1793  else if (luminous) {
+
1794  VideoDX9LuminousVertex* v = new(__FILE__,__LINE__) VideoDX9LuminousVertex[nverts];
+
1795  verts = v;
+
1796  vsize = sizeof(VideoDX9LuminousVertex);
+ +
1798 
+
1799  for (int i = 0; i < nverts; i++) {
+
1800  v->x = vset->loc[i].x;
+
1801  v->y = vset->loc[i].y;
+
1802  v->z = vset->loc[i].z;
+
1803 
+
1804  v->diffuse = vset->diffuse[i];
+
1805 
+
1806  v->tu = vset->tu[i];
+
1807  v->tv = vset->tv[i];
+
1808 
+
1809  v++;
+
1810  }
+
1811  }
+
1812 
+
1813  else {
+
1814  VideoDX9SolidVertex* v = new(__FILE__,__LINE__) VideoDX9SolidVertex[nverts];
+
1815  verts = v;
+
1816  vsize = sizeof(VideoDX9SolidVertex);
+ +
1818 
+
1819  for (int i = 0; i < nverts; i++) {
+
1820  v->x = vset->loc[i].x;
+
1821  v->y = vset->loc[i].y;
+
1822  v->z = vset->loc[i].z;
+
1823 
+
1824  v->nx = vset->nrm[i].x;
+
1825  v->ny = vset->nrm[i].y;
+
1826  v->nz = vset->nrm[i].z;
+
1827 
+
1828  v->tu = vset->tu[i];
+
1829  v->tv = vset->tv[i];
+
1830 
+
1831  v++;
+
1832  }
+
1833  }
+
1834 
+
1835  if (verts && indices) {
+
1836  HRESULT hr = E_FAIL;
+
1837 
+
1838  // fill index array
+
1839  int num_indices = 0;
+
1840  int num_tris = 0;
+
1841 
+
1842  WORD* s = indices;
+
1843  Poly* p = polys;
+
1844 
+
1845  for (int i = 0; i < npolys; i++) {
+
1846  if (p->nverts == 3) {
+
1847  num_indices += 3;
+
1848  num_tris += 1;
+
1849 
+
1850  *s++ = p->verts[0];
+
1851  *s++ = p->verts[1];
+
1852  *s++ = p->verts[2];
+
1853  }
+
1854 
+
1855  else if (p->nverts == 4) {
+
1856  num_indices += 6;
+
1857  num_tris += 2;
+
1858 
+
1859  *s++ = p->verts[0];
+
1860  *s++ = p->verts[1];
+
1861  *s++ = p->verts[2];
+
1862 
+
1863  *s++ = p->verts[0];
+
1864  *s++ = p->verts[2];
+
1865  *s++ = p->verts[3];
+
1866  }
+
1867 
+
1868  p++;
+
1869  }
+
1870 
+
1871  hr = d3ddevice->SetTransform(D3DTS_WORLD, &identity_matrix);
+
1872  hr = d3ddevice->SetVertexShader(NULL);
+
1873  hr = d3ddevice->SetFVF(fvf);
+
1874 
+
1875  // send primitives to the device
+
1876  Material* mtl = polys->material;
+
1877  IDirect3DTexture9* texture = 0;
+
1878 
+
1879  if (mtl && texcache && mtl->tex_diffuse) {
+
1880  texture = texcache->FindTexture(mtl->tex_diffuse);
+
1881  }
+
1882 
+
1883  if (current_texture != texture) {
+
1884  hr = d3ddevice->SetTexture(0, texture);
+
1885  current_texture = texture;
+
1886  }
+
1887 
+
1888  if (mtl && texcache && mtl->tex_detail) {
+
1889  texture = texcache->FindTexture(mtl->tex_detail);
+
1890  hr = d3ddevice->SetTexture(1, texture);
+
1891  }
+
1892 
+
1893  if (mtl && !luminous) {
+
1894  D3DMATERIAL9 d3dmtl;
+
1895  CreateD3DMaterial(d3dmtl, *mtl);
+
1896 
+
1897  hr = d3ddevice->SetMaterial(&d3dmtl);
+
1898  hr = d3ddevice->SetRenderState(D3DRS_AMBIENT, ambient.Value());
+
1899  }
+
1900 
+
1901  // set render states and select buffers
+
1902  SetRenderState(FILL_MODE, D3DFILL_SOLID);
+
1903  SetRenderState(LIGHTING_ENABLE, luminous ? FALSE : TRUE);
+
1904  SetBlendType(mtl->blend);
+
1905 
+
1906  d3ddevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
+
1907  d3ddevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
+
1908  d3ddevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
+
1909  d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
+
1910  d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
+
1911  d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);
+
1912 
+
1913  d3ddevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
+
1914 
+
1915 
+
1916  hr = d3ddevice->DrawIndexedPrimitiveUP(
+
1917  D3DPT_TRIANGLELIST,
+
1918  0,
+
1919  nverts,
+
1920  num_tris,
+
1921  indices,
+
1922  D3DFMT_INDEX16,
+
1923  verts,
+
1924  vsize);
+
1925 
+
1926  if (FAILED(hr)) {
+
1927  static int report = 10;
+
1928  if (report-- > 0)
+
1929  VideoDX9Error("Could not draw 3D polys.", hr);
+
1930  }
+
1931 
+
1932  delete [] verts;
+
1933  delete [] indices;
+
1934 
+
1935  if (SUCCEEDED(hr)) {
+
1936  stats.nverts += nverts;
+
1937  stats.npolys += num_tris;
+
1938  result = true;
+
1939  }
+
1940  }
+
1941  }
+
1942 
+
1943  return result;
+
1944 }
+
1945 
+
1946 // +--------------------------------------------------------------------+
+
1947 
+
1948 bool
+
1949 VideoDX9::DrawScreenPolys(int npolys, Poly* polys, int blend)
+
1950 {
+
1951  bool result = false;
+
1952  HRESULT hr = E_FAIL;
+
1953 
+
1954  if (d3ddevice && polys && npolys > 0 && screen_vbuf && screen_ibuf) {
+
1955  stats.ncalls++;
+
1956 
+
1957  // fill screen vertex buffer
+
1958  if (!PopulateScreenVerts(polys->vertex_set))
+
1959  return false;
+
1960 
+
1961  // fill screen index buffer
+
1962  int num_indices = 0;
+
1963  int num_tris = 0;
+
1964 
+
1965  // count the number of indices needed for these polys
+
1966  for (int i = 0; i < npolys; i++) {
+
1967  Poly* p = polys + i;
+
1968 
+
1969  if (p->nverts == 3) {
+
1970  num_indices += 3;
+
1971  num_tris += 1;
+
1972  }
+
1973 
+
1974  else if (p->nverts == 4) {
+
1975  num_indices += 6;
+
1976  num_tris += 2;
+
1977  }
+
1978  }
+
1979 
+
1980  WORD* screen_indices = screen_ibuf->Lock(num_indices);
+
1981  int first_index = screen_ibuf->GetNextIndex();
+
1982 
+
1983  if (!screen_indices) {
+
1984  Print(" VideoDX9: could not lock screen ibuf for %d indices.\n", num_indices);
+
1985  return false;
+
1986  }
+
1987 
+
1988  // copy the indices into the locked index buffer
+
1989  WORD* s = screen_indices;
+
1990  Poly* p = polys;
+
1991 
+
1992  for (int i = 0; i < npolys; i++) {
+
1993  if (p->nverts == 3) {
+
1994  *s++ = p->verts[0] + first_vert;
+
1995  *s++ = p->verts[1] + first_vert;
+
1996  *s++ = p->verts[2] + first_vert;
+
1997  }
+
1998  else if (p->nverts == 4) {
+
1999  *s++ = p->verts[0] + first_vert;
+
2000  *s++ = p->verts[1] + first_vert;
+
2001  *s++ = p->verts[2] + first_vert;
+
2002 
+
2003  *s++ = p->verts[0] + first_vert;
+
2004  *s++ = p->verts[2] + first_vert;
+
2005  *s++ = p->verts[3] + first_vert;
+
2006  }
+
2007 
+
2008  p++;
+
2009  }
+
2010 
+
2011  screen_ibuf->Unlock();
+
2012 
+
2013  // set render states and select buffers
+
2014  SetRenderState(FILL_MODE, D3DFILL_SOLID);
+
2015  SetRenderState(Z_ENABLE, D3DZB_FALSE);
+
2016  SetRenderState(Z_WRITE_ENABLE, D3DZB_FALSE);
+ +
2018  SetBlendType(blend);
+
2019 
+
2020  d3ddevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
+
2021  d3ddevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
+
2022  d3ddevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
+
2023  d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
+
2024  d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
+
2025  d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);
+
2026 
+
2027  d3ddevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
+
2028 
+
2029  // send primitives to the device
+
2030  Material* mtl = polys->material;
+
2031  IDirect3DTexture9* texture = 0;
+
2032 
+
2033  if (mtl && texcache && mtl->tex_diffuse) {
+
2034  texture = texcache->FindTexture(mtl->tex_diffuse);
+
2035  }
+
2036 
+
2037  if (current_texture != texture) {
+
2038  hr = d3ddevice->SetTexture(0, texture);
+
2039  current_texture = texture;
+
2040  }
+
2041 
+
2042  screen_vbuf->Select(0);
+
2043  screen_ibuf->Select();
+
2044  hr = d3ddevice->SetVertexShader(NULL);
+
2045  hr = d3ddevice->SetFVF(VideoDX9ScreenVertex::FVF);
+
2046 
+
2047  hr = d3ddevice->DrawIndexedPrimitive(
+
2048  D3DPT_TRIANGLELIST,
+
2049  0,
+
2050  first_vert,
+
2051  num_verts,
+
2052  first_index,
+
2053  num_tris);
+
2054 
+
2055  if (FAILED(hr)) {
+
2056  static int report = 10;
+
2057  if (report-- > 0)
+
2058  VideoDX9Error("Could not draw screen polys.", hr);
+
2059  }
+
2060  else {
+
2061  stats.nverts += num_verts;
+
2062  stats.npolys += num_tris;
+
2063  result = true;
+
2064  }
+
2065  }
+
2066 
+
2067  return result;
+
2068 }
+
2069 
+
2070 // +--------------------------------------------------------------------+
+
2071 
+
2072 bool
+
2073 VideoDX9::DrawSolid(Solid* s, DWORD blend_modes)
+
2074 {
+
2075  bool result = false;
+
2076  HRESULT hr = E_FAIL;
+
2077 
+
2078  if (d3ddevice && s && s->GetModel()) {
+
2079  Model* model = s->GetModel();
+
2080  Matrix orient = s->Orientation();
+
2081  orient.Transpose();
+
2082 
+
2083  D3DMATRIX world_matrix;
+
2084  CreateD3DMatrix(world_matrix, orient, s->Location());
+
2085  d3ddevice->SetTransform(D3DTS_WORLD, &world_matrix);
+
2086  matrixWorld = world_matrix;
+
2087  D3DXMatrixInverse(&matrixWorldInverse, 0, &matrixWorld);
+
2088 
+
2089  ListIter<Surface> surf_iter = model->GetSurfaces();
+
2090  while (++surf_iter) {
+
2091  Surface* surf = surf_iter.value();
+
2092 
+
2093  if (surf->IsHidden() || surf->IsSimplified())
+
2094  continue;
+
2095 
+
2096  if (PrepareSurface(surf)) {
+
2097  result = true;
+
2098 
+ +
2100  surf_data->vertex_buffer->Select(0);
+
2101  surf_data->index_buffer->Select();
+
2102 
+
2103  ListIter<Segment> seg_iter = surf->GetSegments();
+
2104  while (++seg_iter) {
+
2105  Segment* segment = seg_iter.value();
+
2106  Material* mtl = segment->material;
+
2107 
+
2108  if (mtl && (blend_modes & mtl->blend)) {
+
2109  result = result && DrawSegment(segment);
+
2110  }
+
2111  }
+
2112  }
+
2113  }
+
2114  }
+
2115 
+
2116  surface_has_tangent_data = false;
+
2117 
+
2118  return result;
+
2119 }
+
2120 
+
2121 bool
+
2122 VideoDX9::DrawSegment(Segment* segment)
+
2123 {
+
2124  bool result = false;
+
2125  bool detail = false;
+
2126  bool luminous = false;
+
2127  HRESULT hr = E_FAIL;
+
2128 
+
2129  if (segment && segment->video_data) {
+
2130  stats.ncalls++;
+
2131 
+
2132  VideoDX9SegmentData* seg_data = (VideoDX9SegmentData*) segment->video_data;
+
2133  int first_vert = seg_data->first_vert;
+
2134  int num_verts = seg_data->num_verts;
+
2135  int first_index = seg_data->first_index;
+
2136  int num_tris = seg_data->num_tris;
+
2137 
+
2138  if (segment->model)
+
2139  luminous = segment->model->IsLuminous();
+
2140 
+
2141  // set render states and select buffers
+
2142  d3ddevice->SetRenderState(D3DRS_AMBIENT, ambient.Value());
+
2143 
+
2144  Material* mtl = segment->material;
+
2145 
+
2146  if (use_material)
+
2147  mtl = use_material;
+
2148 
+
2149  if (segment->polys && segment->polys->vertex_set && segment->polys->vertex_set->tu1)
+
2150  detail = true;
+
2151 
+
2152  // send primitives to the device
+
2153  if (detail) {
+
2154  hr = d3ddevice->SetVertexShader(NULL);
+
2155  hr = d3ddevice->SetFVF(VideoDX9DetailVertex::FVF);
+
2156  }
+
2157 
+
2158  else if (luminous) {
+
2159  hr = d3ddevice->SetVertexShader(NULL);
+
2160  hr = d3ddevice->SetFVF(VideoDX9LuminousVertex::FVF);
+
2161  }
+
2162 
+
2163  else if (surface_has_tangent_data && vertex_declaration) {
+
2164  hr = d3ddevice->SetVertexDeclaration(vertex_declaration);
+
2165  hr = d3ddevice->SetVertexShader(NULL);
+
2166  }
+
2167 
+
2168  else {
+
2169  hr = d3ddevice->SetVertexShader(NULL);
+
2170  hr = d3ddevice->SetFVF(VideoDX9SolidVertex::FVF);
+
2171  }
+
2172 
+
2173  if (render_state[FILL_MODE] == FILL_WIREFRAME) {
+
2174  PrepareMaterial(mtl);
+
2175  SetupPass(0);
+
2176 
+
2177  for (int i = 0; i < segment->npolys; i++) {
+
2178  DrawPolyOutline(segment->polys + i);
+
2179  }
+
2180  }
+
2181 
+
2182  else if (luminous) {
+
2183  PrepareMaterial(mtl);
+
2184 
+
2185  SetRenderState(FILL_MODE, D3DFILL_SOLID);
+ +
2187  SetBlendType(mtl->blend);
+
2188 
+
2189  for (int pass = 0; pass < passes; pass++) {
+
2190  SetupPass(pass);
+
2191 
+
2192  hr = d3ddevice->DrawIndexedPrimitive(
+
2193  D3DPT_TRIANGLELIST,
+
2194  0,
+
2195  first_vert,
+
2196  num_verts,
+
2197  first_index,
+
2198  num_tris);
+
2199  }
+
2200 
+
2201  d3ddevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
+
2202  }
+
2203 
+
2204  else {
+
2205  PrepareMaterial(mtl);
+
2206 
+
2207  if (strategy == DX9_STRATEGY_GLOW && render_state[LIGHTING_PASS] > 0) {
+
2208  hr = 0;
+
2209  }
+
2210 
+
2211  else if (magic_fx && strategy < DX9_STRATEGY_BLEND && !detail) {
+
2212  DWORD vs_version = 0;
+
2213  DWORD ps_version = 0;
+
2214  bool shaders_ok = false;
+
2215 
+
2216  VideoDX9DeviceInfo* dev_info = dx9enum->GetDeviceInfo(video_settings.GetDeviceType());
+
2217 
+
2218  if (dev_info) {
+
2219  vs_version = video_settings.enable_vs ? dev_info->caps.VertexShaderVersion : 0;
+
2220  ps_version = video_settings.enable_ps ? dev_info->caps.PixelShaderVersion : 0;
+
2221 
+
2222  if (vs_version >= D3DVS_VERSION(1,1))
+
2223  shaders_ok = true;
+
2224  }
+
2225 
+
2226  if (surface_has_tangent_data && vertex_declaration) {
+
2227  hr = d3ddevice->SetVertexShader(NULL);
+
2228  hr = d3ddevice->SetVertexDeclaration(vertex_declaration);
+
2229  }
+
2230 
+
2231  else {
+
2232  hr = d3ddevice->SetVertexShader(NULL);
+
2233  hr = d3ddevice->SetFVF(VideoDX9SolidVertex::FVF);
+
2234  }
+
2235 
+
2236  bool would_bump = !IsBumpMapEnabled() && mtl->bump > 0.5;
+
2237 
+
2238  bool will_bump = IsBumpMapEnabled() && surface_has_tangent_data && shaders_ok && camera;
+
2239 
+
2240  bool do_pix = will_bump && render_state[LIGHTING_PASS] == 0;
+
2241  bool do_bump = will_bump && render_state[LIGHTING_PASS] > 0;
+
2242 
+
2243  D3DXMATRIX matrixWVP = matrixWorld * matrixView * matrixProj;
+
2244 
+
2245  D3DXVECTOR4 eyePos( (float) camera->Pos().x, (float) camera->Pos().y, (float) camera->Pos().z, 1.0f);
+
2246 
+
2247  D3DXVECTOR4 eyeObj;
+
2248  D3DXVec4Transform(&eyeObj, &eyePos, &matrixWorldInverse);
+
2249 
+
2250  D3DXVECTOR4 lightPos(100.0f, 100.0f, 100.0f, 1.0f);
+
2251  D3DXVECTOR4 lightColor(1,1,1,1);
+
2252  D3DXVECTOR4 ambientColor(0,0,0,1);
+
2253 
+
2254  ambientColor.x = ambient.fRed();
+
2255  ambientColor.y = ambient.fGreen();
+
2256  ambientColor.z = ambient.fBlue();
+
2257 
+
2258  if (main_light && (render_state[LIGHTING_PASS] > 0 || mtl->blend > Material::MTL_SOLID)) {
+
2259  lightPos.x = (float) main_light->Location().x;
+
2260  lightPos.y = (float) main_light->Location().y;
+
2261  lightPos.z = (float) main_light->Location().z;
+
2262 
+
2263  if (mtl->tex_bumpmap && do_bump)
+
2264  D3DXVec4Transform(&lightPos, &lightPos, &matrixWorldInverse);
+
2265 
+
2266  lightColor.x = main_light->GetColor().fRed() * main_light->Intensity();
+
2267  lightColor.y = main_light->GetColor().fGreen() * main_light->Intensity();
+
2268  lightColor.z = main_light->GetColor().fBlue() * main_light->Intensity();
+
2269  lightColor.w = 1.0f;
+
2270  }
+
2271 
+
2272  else if (back_light && render_state[LIGHTING_PASS] == 0) {
+
2273  lightPos.x = (float) back_light->Location().x;
+
2274  lightPos.y = (float) back_light->Location().y;
+
2275  lightPos.z = (float) back_light->Location().z;
+
2276 
+
2277  lightColor.x = back_light->GetColor().fRed() * back_light->Intensity();
+
2278  lightColor.y = back_light->GetColor().fGreen() * back_light->Intensity();
+
2279  lightColor.z = back_light->GetColor().fBlue() * back_light->Intensity();
+
2280  lightColor.w = 1.0f;
+
2281  }
+
2282 
+
2283  D3DXVECTOR4 lightDir = D3DXVECTOR4(0.0f, 0.0f, 0.0f, 0.0f) - lightPos;
+
2284  D3DXVec4Normalize(&lightDir, &lightDir);
+
2285 
+
2286  magic_fx->SetMatrix("wvp", &matrixWVP);
+
2287  magic_fx->SetMatrix("world", &matrixWorld);
+
2288  magic_fx->SetMatrix("view", &matrixView);
+
2289  magic_fx->SetMatrix("proj", &matrixProj);
+
2290  magic_fx->SetMatrix("worldInv", &matrixWorldInverse);
+
2291 
+
2292  magic_fx->SetVector("light1Pos", &lightPos);
+
2293  magic_fx->SetVector("light1Dir", &lightDir);
+
2294  magic_fx->SetVector("light1Color", &lightColor);
+
2295  magic_fx->SetVector("ambientColor", &ambientColor);
+
2296  magic_fx->SetVector("eyeObj", &eyeObj);
+
2297 
+
2298  FLOAT base_bias = (FLOAT) (DW2I(render_state[Z_BIAS]) / -10000.0);
+
2299  magic_fx->SetFloat("bias", base_bias + video_settings.depth_bias);
+
2300 
+
2301  ColorValue orig_ks = mtl->Ks;
+
2302 
+
2303  if (would_bump && mtl->specular_value >= 0.5)
+
2304  mtl->Ks = mtl->Ks * 0.3;
+
2305 
+
2306  magic_fx->SetValue("Ka", &mtl->Ka, sizeof(ColorValue));
+
2307  magic_fx->SetValue("Kd", &mtl->Kd, sizeof(ColorValue));
+
2308  magic_fx->SetValue("Ke", &mtl->Ke, sizeof(ColorValue));
+
2309  magic_fx->SetValue("Ks", &mtl->Ks, sizeof(ColorValue));
+
2310  magic_fx->SetFloat("Ns", mtl->power);
+
2311 
+
2312  if (would_bump && mtl->specular_value >= 0.5)
+
2313  mtl->Ks = orig_ks;
+
2314 
+
2315  if (mtl->tex_diffuse) {
+
2316  IDirect3DTexture9* texture = texcache->FindTexture(mtl->tex_diffuse);
+
2317  magic_fx->SetTexture("tex_d", texture);
+
2318  } else {
+
2319  magic_fx->SetTexture("tex_d", 0);
+
2320  }
+
2321 
+
2322  if (mtl->tex_emissive) {
+
2323  IDirect3DTexture9* texture = texcache->FindTexture(mtl->tex_emissive);
+
2324  magic_fx->SetTexture("tex_e", texture);
+
2325  } else {
+
2326  magic_fx->SetTexture("tex_e", 0);
+
2327  }
+
2328 
+
2329  if (mtl->tex_specular && IsSpecMapEnabled()) {
+
2330  IDirect3DTexture9* texture = texcache->FindTexture(mtl->tex_specular);
+
2331  magic_fx->SetTexture("tex_s", texture);
+
2332  } else {
+
2333  magic_fx->SetTexture("tex_s", 0);
+
2334  }
+
2335 
+
2336  if (mtl->tex_bumpmap && do_bump) {
+
2337  IDirect3DTexture9* texture = texcache->FindNormalMap(mtl->tex_bumpmap, mtl->bump);
+
2338  magic_fx->SetTexture("tex_n", texture);
+
2339  magic_fx->SetFloat("offsetAmp", mtl->bump / mtl->tex_bumpmap->Height());
+
2340  } else if (mtl->tex_bumpmap && !do_bump) {
+
2341  IDirect3DTexture9* texture = texcache->FindTexture(mtl->tex_bumpmap);
+
2342  magic_fx->SetTexture("tex_x", texture);
+
2343  } else {
+
2344  magic_fx->SetTexture("tex_x", 0);
+
2345  }
+
2346 
+
2347  const char* mtl_shader = mtl->GetShader(render_state[LIGHTING_PASS]);
+
2348  D3DXHANDLE hnd_shader = 0;
+
2349 
+
2350  if (mtl_shader) {
+
2351  if (!strcmp(mtl_shader, "null"))
+
2352  return true;
+
2353 
+
2354  hnd_shader = magic_fx->GetTechniqueByName(mtl_shader);
+
2355  }
+
2356 
+
2357  if (hnd_shader) {
+
2358  hr = magic_fx->SetTechnique(hnd_shader);
+
2359  } else {
+
2360  if (will_bump) {
+
2361  if (mtl->tex_specular && IsSpecMapEnabled()) {
+
2362  if (mtl->tex_bumpmap && do_bump) {
+
2363  if (ps_version >= D3DPS_VERSION(2,0))
+
2364  hr = magic_fx->SetTechnique("BumpSpecMapPix");
+
2365  else
+
2366  hr = magic_fx->SetTechnique("BumpSpecMap");
+
2367  } else if (mtl->tex_emissive && render_state[LIGHTING_PASS] == 0) {
+
2368  if (ps_version >= D3DPS_VERSION(2,0))
+
2369  hr = magic_fx->SetTechnique("EmissiveSpecMapPix");
+
2370  else
+
2371  hr = magic_fx->SetTechnique("EmissiveSpecularTexture");
+
2372  } else {
+
2373  if (ps_version >= D3DPS_VERSION(2,0))
+
2374  hr = magic_fx->SetTechnique("SpecMapPix");
+
2375  else
+
2376  hr = magic_fx->SetTechnique("SpecularTexture");
+
2377  }
+
2378  } else {
+
2379  if (mtl->tex_bumpmap && do_bump) {
+
2380  if (ps_version >= D3DPS_VERSION(2,0))
+
2381  hr = magic_fx->SetTechnique("BumpMapPix");
+
2382  else
+
2383  hr = magic_fx->SetTechnique("BumpMap");
+
2384  } else if (mtl->tex_emissive && render_state[LIGHTING_PASS] == 0) {
+
2385  if (ps_version >= D3DPS_VERSION(2,0))
+
2386  hr = magic_fx->SetTechnique("EmissivePix");
+
2387  else
+
2388  hr = magic_fx->SetTechnique("EmissiveTexture");
+
2389  } else {
+
2390  if (ps_version >= D3DPS_VERSION(2,0))
+
2391  hr = magic_fx->SetTechnique("SimplePix");
+
2392  else
+
2393  hr = magic_fx->SetTechnique("SimpleTexture");
+
2394  }
+
2395  }
+
2396  }
+
2397 
+
2398  else if (texcache && mtl->tex_diffuse) {
+
2399  if (mtl->tex_specular && IsSpecMapEnabled()) {
+
2400  if (mtl->tex_emissive && render_state[LIGHTING_PASS] == 0) {
+
2401  hr = magic_fx->SetTechnique("EmissiveSpecularTexture");
+
2402  } else {
+
2403  hr = magic_fx->SetTechnique("SpecularTexture");
+
2404  }
+
2405  }
+
2406 
+
2407  else {
+
2408  if (mtl->tex_emissive && render_state[LIGHTING_PASS] == 0) {
+
2409  hr = magic_fx->SetTechnique("EmissiveTexture");
+
2410  } else {
+
2411  hr = magic_fx->SetTechnique("SimpleTexture");
+
2412  }
+
2413  }
+
2414  } else {
+
2415  hr = magic_fx->SetTechnique("SimpleMaterial");
+
2416  }
+
2417  }
+
2418 
+
2419  if (environment_cube != 0 && magic_fx->IsParameterUsed("env_cube", hnd_shader)) {
+
2420  D3DXMATRIX env_matrix;
+
2421  D3DXMatrixIdentity(&env_matrix);
+
2422 
+
2423  magic_fx->SetMatrix("env_matrix", &env_matrix);
+
2424  magic_fx->SetTexture("env_cube", environment_cube->GetTexture());
+
2425  }
+
2426 
+
2427  if (render_state[STENCIL_ENABLE]) {
+
2428  d3ddevice->SetRenderState(D3DRS_STENCILENABLE, TRUE);
+
2429  d3ddevice->SetRenderState(D3DRS_STENCILREF, 0x01);
+
2430  d3ddevice->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_GREATER);
+
2431  } else {
+
2432  d3ddevice->SetRenderState(D3DRS_STENCILENABLE, FALSE);
+
2433  }
+
2434 
+
2435  if (render_state[LIGHTING_PASS] > 0) {
+
2436  current_blend_state = 100;
+ + +
2439  } else {
+
2440  current_blend_state = 100;
+
2441  SetBlendType(mtl->blend);
+
2442  }
+
2443 
+
2444  UINT nPasses = 0;
+
2445 
+
2446  hr = magic_fx->Begin(&nPasses, 0);
+
2447 
+
2448  for (UINT i = 0; i < nPasses; i++) {
+
2449  hr = magic_fx->BeginPass(i);
+
2450 
+
2451  hr = d3ddevice->DrawIndexedPrimitive(
+
2452  D3DPT_TRIANGLELIST,
+
2453  0,
+
2454  first_vert,
+
2455  num_verts,
+
2456  first_index,
+
2457  num_tris);
+
2458 
+
2459  hr = magic_fx->EndPass();
+
2460  }
+
2461 
+
2462  hr = magic_fx->End();
+
2463  } else {
+
2464  for (int pass = 0; pass < passes; pass++) {
+
2465  SetupPass(pass);
+
2466 
+
2467  hr = d3ddevice->DrawIndexedPrimitive(
+
2468  D3DPT_TRIANGLELIST,
+
2469  0,
+
2470  first_vert,
+
2471  num_verts,
+
2472  first_index,
+
2473  num_tris);
+
2474 
+
2475  if (detail) {
+
2476  hr = d3ddevice->SetVertexShader(NULL);
+
2477  hr = d3ddevice->SetFVF(VideoDX9DetailVertex::FVF);
+
2478  } else if (luminous) {
+
2479  hr = d3ddevice->SetVertexShader(NULL);
+
2480  hr = d3ddevice->SetFVF(VideoDX9LuminousVertex::FVF);
+
2481  } else if (surface_has_tangent_data && vertex_declaration) {
+
2482  hr = d3ddevice->SetVertexShader(NULL);
+
2483  hr = d3ddevice->SetVertexDeclaration(vertex_declaration);
+
2484  } else {
+
2485  hr = d3ddevice->SetVertexShader(NULL);
+
2486  hr = d3ddevice->SetFVF(VideoDX9SolidVertex::FVF);
+
2487  }
+
2488  }
+
2489  }
+
2490  }
+
2491 
+
2492  if (FAILED(hr)) {
+
2493  static int report = 10;
+
2494  if (report-- > 0)
+
2495  VideoDX9Error("Could not draw solid polys.", hr);
+
2496  } else {
+
2497  stats.nverts += num_verts;
+
2498  stats.npolys += num_tris;
+
2499  result = true;
+
2500  }
+
2501  }
+
2502 
+
2503  return result;
+
2504 }
+
2505 
+
2506 bool
+ +
2508 {
+
2509  if (d3ddevice && p && p->nverts >= 3) {
+
2510  static VideoDX9LineVertex verts[8];
+
2511 
+
2512  int nlines = p->nverts;
+
2513  VertexSet* vset = p->vertex_set;
+
2514  WORD index = 0;
+
2515  Color color = Color::Black;
+
2516  HRESULT hr = E_FAIL;
+
2517 
+
2518  ZeroMemory(verts, sizeof(verts));
+
2519 
+
2520  if (p->material)
+
2521  color = p->material->Kd.ToColor();
+
2522 
+
2523  for (int i = 0; i < p->nverts; i++) {
+
2524  index = p->verts[i];
+
2525 
+
2526  verts[i].x = vset->loc[index].x;
+
2527  verts[i].y = vset->loc[index].y;
+
2528  verts[i].z = vset->loc[index].z;
+
2529  verts[i].diffuse = color.Value();
+
2530  }
+
2531 
+
2532  // last vertex, to close the loop
+
2533  index = p->verts[0];
+
2534  int i = p->nverts;
+
2535 
+
2536  verts[i].x = vset->loc[index].x;
+
2537  verts[i].y = vset->loc[index].y;
+
2538  verts[i].z = vset->loc[index].z;
+
2539  verts[i].diffuse = color.Value();
+
2540 
+
2541  current_texture = 0;
+
2542 
+
2543  hr = d3ddevice->SetVertexShader(NULL);
+
2544  hr = d3ddevice->SetFVF(VideoDX9LineVertex::FVF);
+
2545  hr = d3ddevice->SetTexture(0, 0);
+
2546  hr = d3ddevice->DrawPrimitiveUP(
+
2547  D3DPT_LINESTRIP,
+
2548  nlines,
+
2549  verts,
+
2550  sizeof(VideoDX9LineVertex));
+
2551  return true;
+
2552  }
+
2553 
+
2554  return false;
+
2555 }
+
2556 
+
2557 // +--------------------------------------------------------------------+
+
2558 
+
2559 bool
+
2560 VideoDX9::DrawShadow(Solid* s, int nverts, Vec3* shadow_verts, bool visible)
+
2561 {
+
2562  bool result = false;
+
2563  HRESULT hr = E_FAIL;
+
2564 
+
2565  if (d3ddevice && s && nverts && shadow_verts && IsShadowEnabled()) {
+
2566  Matrix orient = s->Orientation();
+
2567  orient.Transpose();
+
2568 
+
2569  D3DMATRIX world_matrix;
+
2570  CreateD3DMatrix(world_matrix, orient, s->Location());
+
2571  d3ddevice->SetTransform(D3DTS_WORLD, &world_matrix);
+
2572  matrixWorld = world_matrix;
+
2573 
+
2574  // show shadow outlines:
+
2575  if (visible) {
+
2576  static VideoDX9LineVertex verts[4];
+
2577 
+
2578  d3ddevice->SetRenderState(D3DRS_ZENABLE, TRUE);
+
2579  d3ddevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
+
2580  d3ddevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESSEQUAL);
+
2581  d3ddevice->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_FLAT);
+
2582  d3ddevice->SetRenderState(D3DRS_LIGHTING, FALSE);
+
2583  d3ddevice->SetVertexShader(NULL);
+
2584  d3ddevice->SetFVF(VideoDX9LineVertex::FVF);
+
2585  d3ddevice->SetTexture(0, 0);
+
2586 
+ +
2588 
+
2589  for (int i = 0; i < nverts; i+=3) {
+
2590  DWORD c = 0xa0ffff80;
+
2591 
+
2592  verts[0].x = shadow_verts[i+0].x;
+
2593  verts[0].y = shadow_verts[i+0].y;
+
2594  verts[0].z = shadow_verts[i+0].z;
+
2595  verts[0].diffuse = c;
+
2596 
+
2597  verts[1].x = shadow_verts[i+1].x;
+
2598  verts[1].y = shadow_verts[i+1].y;
+
2599  verts[1].z = shadow_verts[i+1].z;
+
2600  verts[1].diffuse = c;
+
2601 
+
2602  verts[2].x = shadow_verts[i+2].x;
+
2603  verts[2].y = shadow_verts[i+2].y;
+
2604  verts[2].z = shadow_verts[i+2].z;
+
2605  verts[2].diffuse = c;
+
2606 
+
2607  verts[3].x = shadow_verts[i+0].x;
+
2608  verts[3].y = shadow_verts[i+0].y;
+
2609  verts[3].z = shadow_verts[i+0].z;
+
2610  verts[3].diffuse = c;
+
2611 
+
2612  hr = d3ddevice->DrawPrimitiveUP(
+
2613  D3DPT_LINESTRIP,
+
2614  3,
+
2615  verts,
+
2616  sizeof(VideoDX9LineVertex));
+
2617  }
+
2618 
+
2619  // restore lighting state
+
2620  d3ddevice->SetRenderState(D3DRS_LIGHTING, render_state[LIGHTING_ENABLE]);
+
2621  }
+
2622 
+
2623  // render shadows into stencil buffer:
+
2624 
+
2625  // Disable z-buffer writes (note: z-testing still occurs), and enable the
+
2626  // stencil-buffer
+
2627  d3ddevice->SetRenderState(D3DRS_ZENABLE, TRUE);
+
2628  d3ddevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
+
2629  d3ddevice->SetRenderState(D3DRS_STENCILENABLE, TRUE);
+
2630 
+
2631  // Dont bother with interpolating color
+
2632  d3ddevice->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_FLAT);
+
2633 
+
2634  // Set up stencil compare fuction, reference value, and masks.
+
2635  // Stencil test passes if ((ref & mask) cmpfn (stencil & mask)) is true.
+
2636  // Note: since we set up the stencil-test to always pass, the STENCILFAIL
+
2637  // renderstate is really not needed.
+
2638  d3ddevice->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS );
+
2639  d3ddevice->SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_KEEP );
+
2640  d3ddevice->SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_KEEP );
+
2641 
+
2642  // If z-test passes, inc/decrement stencil buffer value
+
2643  d3ddevice->SetRenderState(D3DRS_STENCILREF, 0x1 );
+
2644  d3ddevice->SetRenderState(D3DRS_STENCILMASK, 0xff );
+
2645  d3ddevice->SetRenderState(D3DRS_STENCILWRITEMASK, 0xff );
+
2646  d3ddevice->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_INCR );
+
2647 
+
2648  // Make sure that no pixels get drawn to the frame buffer
+
2649  d3ddevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE );
+
2650  d3ddevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ZERO );
+
2651  d3ddevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE );
+
2652 
+
2653  d3ddevice->SetVertexShader(NULL);
+
2654  d3ddevice->SetFVF(D3DFVF_XYZ);
+
2655 
+
2656  // Draw front-side of shadow volume in stencil/z only
+
2657  hr = d3ddevice->DrawPrimitiveUP(D3DPT_TRIANGLELIST, nverts/3, shadow_verts, sizeof(Vec3));
+
2658 
+
2659  // Now reverse cull order so back sides of shadow volume are written.
+
2660  d3ddevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW );
+
2661 
+
2662  // Decrement stencil buffer value
+
2663  d3ddevice->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_DECR );
+
2664 
+
2665  // Draw back-side of shadow volume in stencil/z only
+
2666  hr = d3ddevice->DrawPrimitiveUP(D3DPT_TRIANGLELIST, nverts/3, shadow_verts, sizeof(Vec3));
+
2667 
+
2668  // restore render states
+
2669  d3ddevice->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_GOURAUD);
+
2670  d3ddevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
+
2671  d3ddevice->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);
+
2672  d3ddevice->SetRenderState(D3DRS_STENCILENABLE, FALSE);
+
2673 
+
2674  // force restore of current blend type
+
2675  int type = current_blend_state;
+
2676  current_blend_state = 100;
+
2677  SetBlendType(type);
+
2678 
+
2679  result = SUCCEEDED(hr);
+
2680  }
+
2681 
+
2682  return result;
+
2683 }
+
2684 
+
2685 // +--------------------------------------------------------------------+
+
2686 
+
2687 bool
+
2688 VideoDX9::DrawLines(int nlines, Vec3* points, Color c, int blend)
+
2689 {
+
2690  bool result = false;
+
2691 
+
2692  if (d3ddevice && points && nlines > 0 && nlines <= 256) {
+
2693  stats.ncalls++;
+
2694 
+
2695  VideoDX9LineVertex* verts = line_verts;
+
2696 
+
2697  if (verts) {
+
2698  HRESULT hr = E_FAIL;
+
2699 
+
2700  for (int i = 0; i < 2*nlines; i++) {
+
2701  VideoDX9LineVertex* v = verts + i;
+
2702  Vec3* p = points + i;
+
2703 
+
2704  v->x = p->x;
+
2705  v->y = p->y;
+
2706  v->z = p->z;
+
2707  v->diffuse = c.Value();
+
2708  }
+
2709 
+
2710  hr = d3ddevice->SetTransform(D3DTS_WORLD, &identity_matrix);
+
2711  hr = d3ddevice->SetVertexShader(NULL);
+
2712  hr = d3ddevice->SetFVF(VideoDX9LineVertex::FVF);
+
2713 
+
2714  DWORD old_lighting = render_state[LIGHTING_ENABLE];
+
2715 
+
2716  // untextured lines:
+
2717  if (current_texture) {
+
2718  d3ddevice->SetTexture(0, 0);
+
2719  current_texture = 0;
+
2720  }
+
2721 
+ +
2723  SetBlendType(blend);
+
2724 
+
2725  hr = d3ddevice->DrawPrimitiveUP(
+
2726  D3DPT_LINELIST,
+
2727  nlines,
+
2728  verts,
+
2729  sizeof(VideoDX9LineVertex));
+
2730 
+
2731  if (FAILED(hr)) {
+
2732  static int report = 10;
+
2733  if (report-- > 0)
+
2734  VideoDX9Error("Could not draw 3D lines.", hr);
+
2735  }
+
2736 
+
2737  SetRenderState(LIGHTING_ENABLE, old_lighting);
+
2738 
+
2739  if (SUCCEEDED(hr)) {
+
2740  stats.nverts += 2*nlines;
+
2741  stats.nlines += nlines;
+
2742  result = true;
+
2743  }
+
2744  }
+
2745  }
+
2746 
+
2747  return result;
+
2748 }
+
2749 
+
2750 // +--------------------------------------------------------------------+
+
2751 
+
2752 bool
+
2753 VideoDX9::DrawScreenLines(int nlines, float* points, Color c, int blend)
+
2754 {
+
2755  bool result = false;
+
2756 
+
2757  if (d3ddevice && points && nlines > 0 && nlines <= 64) {
+
2758  stats.ncalls++;
+
2759 
+
2760  VideoDX9ScreenVertex* verts = screen_line_verts;
+
2761 
+
2762  if (verts) {
+
2763  HRESULT hr = E_FAIL;
+
2764 
+
2765  for (int i = 0; i < 2*nlines; i++) {
+
2766  VideoDX9ScreenVertex* v = verts + i;
+
2767 
+
2768  v->sx = points[2*i + 0];
+
2769  v->sy = points[2*i + 1];
+
2770  v->sz = 0.0f;
+
2771  v->rhw = 1.0f;
+
2772  v->diffuse = c.Value();
+
2773  v->tu = 0.0f;
+
2774  v->tv = 0.0f;
+
2775  }
+
2776 
+
2777  hr = d3ddevice->SetVertexShader(NULL);
+
2778  hr = d3ddevice->SetFVF(VideoDX9ScreenVertex::FVF);
+
2779 
+
2780  if (FAILED(hr)) {
+
2781  static int report = 10;
+
2782  if (report-- > 0)
+
2783  VideoDX9Error("Could not set FVF for screen lines.", hr);
+
2784  }
+
2785 
+
2786  else {
+
2787  if (current_texture != 0) {
+
2788  hr = d3ddevice->SetTexture(0, 0);
+
2789  current_texture = 0;
+
2790  }
+
2791 
+
2792  SetRenderState(FILL_MODE, D3DFILL_SOLID);
+
2793  SetRenderState(Z_ENABLE, D3DZB_FALSE);
+ +
2795  SetBlendType(blend);
+
2796 
+
2797  hr = d3ddevice->DrawPrimitiveUP(
+
2798  D3DPT_LINELIST,
+
2799  nlines,
+
2800  verts,
+
2801  sizeof(VideoDX9ScreenVertex));
+
2802 
+
2803  if (FAILED(hr)) {
+
2804  static int report = 10;
+
2805  if (report-- > 0)
+
2806  VideoDX9Error("Could not draw screen lines.", hr);
+
2807  }
+
2808  }
+
2809 
+
2810  if (SUCCEEDED(hr)) {
+
2811  stats.nverts += 2*nlines;
+
2812  stats.nlines += nlines;
+
2813  result = true;
+
2814  }
+
2815  }
+
2816  }
+
2817 
+
2818  return result;
+
2819 }
+
2820 
+
2821 // +--------------------------------------------------------------------+
+
2822 
+
2823 bool
+ +
2825 {
+
2826  if (vset && vset->nverts) {
+
2827  HRESULT hr = E_FAIL;
+
2828 
+
2829  int nverts = vset->nverts;
+
2830  VideoDX9LineVertex* verts = new(__FILE__,__LINE__) VideoDX9LineVertex[nverts];
+
2831 
+
2832  if (verts) {
+
2833  for (int i = 0; i < nverts; i++) {
+
2834  VideoDX9LineVertex* v = verts + i;
+
2835  Vec3* p = vset->loc + i;
+
2836 
+
2837  v->x = p->x;
+
2838  v->y = p->y;
+
2839  v->z = p->z;
+
2840  v->diffuse = vset->diffuse[i];
+
2841  }
+
2842 
+ +
2844 
+
2845  hr = d3ddevice->SetTransform(D3DTS_WORLD, &identity_matrix);
+
2846  hr = d3ddevice->SetVertexShader(NULL);
+
2847  hr = d3ddevice->SetFVF(VideoDX9LineVertex::FVF);
+
2848  hr = d3ddevice->SetTexture(0, 0);
+
2849  hr = d3ddevice->DrawPrimitiveUP(
+
2850  D3DPT_POINTLIST,
+
2851  nverts,
+
2852  verts,
+
2853  sizeof(VideoDX9LineVertex));
+
2854 
+
2855  delete [] verts;
+
2856  return true;
+
2857  }
+
2858  }
+
2859 
+
2860  return false;
+
2861 }
+
2862 
+
2863 // +--------------------------------------------------------------------+
+
2864 
+
2865 bool
+ +
2867 {
+
2868  use_material = m;
+
2869  return true;
+
2870 }
+
2871 
+
2872 // +--------------------------------------------------------------------+
+
2873 
+
2874 bool
+
2875 VideoDX9::UseXFont(const char* name, int size, bool bold, bool ital)
+
2876 {
+
2877  if (d3ddevice && name && *name && size > 4) {
+
2878  RELEASE(d3dx_font);
+
2879 
+
2880  strcpy_s(font_name, name);
+
2881  font_size = size;
+
2882  font_bold = bold;
+
2883  font_ital = ital;
+
2884 
+
2885  HRESULT hr = E_FAIL;
+
2886  HDC hdc = GetDC(NULL);
+
2887  int nLogPixelsY = GetDeviceCaps(hdc, LOGPIXELSY);
+
2888 
+
2889  ReleaseDC(NULL, hdc);
+
2890 
+
2891  int nHeight = -size * nLogPixelsY / 72;
+
2892 
+
2893  hr = D3DXCreateFont(d3ddevice, // D3D device
+
2894  nHeight, // Height
+
2895  0, // Width
+
2896  bold ? FW_BOLD : FW_NORMAL, // Weight
+
2897  1, // MipLevels, 0 = autogen mipmaps
+
2898  ital, // Italic
+
2899  DEFAULT_CHARSET, // CharSet
+
2900  OUT_DEFAULT_PRECIS, // OutputPrecision
+
2901  DEFAULT_QUALITY, // Quality
+
2902  DEFAULT_PITCH | FF_DONTCARE, // PitchAndFamily
+
2903  name, // pFaceName
+
2904  &d3dx_font); // ppFont
+
2905 
+
2906  if (SUCCEEDED(hr)) {
+
2907  return true;
+
2908  }
+
2909  }
+
2910 
+
2911  RELEASE(d3dx_font);
+
2912  return false;
+
2913 }
+
2914 
+
2915 bool
+
2916 VideoDX9::DrawText(const char* text, int count, const Rect& rect, DWORD format, Color c)
+
2917 {
+
2918  if (d3ddevice && text && *text && d3dx_font) {
+
2919  RECT r;
+
2920  r.left = rect.x;
+
2921  r.top = rect.y;
+
2922  r.right = rect.x + rect.w;
+
2923  r.bottom = rect.y + rect.h;
+
2924 
+
2925  d3dx_font->DrawText(0, text, count, &r, format, c.Value());
+
2926  }
+
2927 
+
2928  return false;
+
2929 }
+
2930 
+
2931 // +--------------------------------------------------------------------+
+
2932 
+
2933 bool
+
2934 VideoDX9::PrepareSurface(Surface* surf)
+
2935 {
+
2936  if (surf) {
+
2937  int nverts = surf->NumVerts();
+
2938  int nindices = surf->NumIndices();
+
2939  bool detail = surf->GetVertexSet()->tu1 != 0;
+
2940  bool luminous = false;
+
2941  DWORD dynamic = 0;
+
2942 
+
2943  if (surf->GetModel()) {
+
2944  luminous = surf->GetModel()->IsLuminous();
+
2945  dynamic = surf->GetModel()->IsDynamic() ? D3DUSAGE_DYNAMIC : 0;
+
2946  }
+
2947 
+
2948  surface_has_tangent_data = !luminous && (surf->GetVertexSet()->tangent && surf->GetVertexSet()->binormal);
+
2949 
+ +
2951 
+
2952  if (!surf_data) {
+
2953  surf_data = new(__FILE__,__LINE__) VideoDX9SurfaceData(surf->GetModel());
+
2954 
+
2955  surface_has_tangent_data = false;
+
2956 
+
2957  if (surf->GetVertexSet()->tangent && surf->GetVertexSet()->binormal) {
+
2958  surface_has_tangent_data = true;
+
2959  surf_data->vertex_buffer = new(__FILE__,__LINE__) VideoDX9VertexBuffer(
+
2960  this,
+
2961  nverts,
+
2962  sizeof(VideoDX9NormalVertex),
+
2963  0, // not an FVF vertex buffer
+
2964  dynamic | D3DUSAGE_WRITEONLY);
+
2965  }
+
2966 
+
2967  else if (detail) {
+
2968  surf_data->vertex_buffer = new(__FILE__,__LINE__) VideoDX9VertexBuffer(
+
2969  this,
+
2970  nverts,
+
2971  sizeof(VideoDX9DetailVertex),
+ +
2973  dynamic | D3DUSAGE_WRITEONLY);
+
2974  }
+
2975 
+
2976  else if (luminous) {
+
2977  surf_data->vertex_buffer = new(__FILE__,__LINE__) VideoDX9VertexBuffer(
+
2978  this,
+
2979  nverts,
+
2980  sizeof(VideoDX9LuminousVertex),
+ +
2982  dynamic | D3DUSAGE_WRITEONLY);
+
2983  }
+
2984 
+
2985  else {
+
2986  surf_data->vertex_buffer = new(__FILE__,__LINE__) VideoDX9VertexBuffer(
+
2987  this,
+
2988  nverts,
+
2989  sizeof(VideoDX9SolidVertex),
+ +
2991  dynamic | D3DUSAGE_WRITEONLY);
+
2992  }
+
2993 
+
2994  surf_data->index_buffer = new(__FILE__,__LINE__) VideoDX9IndexBuffer(
+
2995  this,
+
2996  nindices,
+
2997  dynamic | D3DUSAGE_WRITEONLY);
+
2998 
+
2999  if (!surf_data->vertex_buffer || !surf_data->index_buffer) {
+
3000  Print("VideoDX9: Unable to prepare surface '%s'\n", surf->Name());
+
3001  delete surf_data;
+
3002  return false;
+
3003  }
+
3004 
+
3005  surf->SetVideoPrivateData(surf_data);
+
3006  }
+
3007 
+
3008  if (surf_data && !surf_data->IsValid()) {
+
3009  if (detail) {
+
3010  VideoDX9DetailVertex* v = (VideoDX9DetailVertex*) surf_data->vertex_buffer->Lock(nverts);
+
3011 
+
3012  if (v) {
+
3013  const VertexSet* vset = surf->GetVertexSet();
+
3014  for (int i = 0; i < nverts; i++) {
+
3015  v->x = vset->loc[i].x;
+
3016  v->y = vset->loc[i].y;
+
3017  v->z = vset->loc[i].z;
+
3018 
+
3019  v->diffuse = vset->diffuse[i];
+
3020  v->specular = vset->specular[i];
+
3021 
+
3022  v->tu = vset->tu[i];
+
3023  v->tv = vset->tv[i];
+
3024  v->tu1 = vset->tu1[i];
+
3025  v->tv1 = vset->tv1[i];
+
3026 
+
3027  v++;
+
3028  }
+
3029 
+
3030  surf_data->vertex_buffer->Unlock();
+
3031  }
+
3032  }
+
3033 
+
3034  else if (luminous) {
+
3035  VideoDX9LuminousVertex* v = (VideoDX9LuminousVertex*) surf_data->vertex_buffer->Lock(nverts);
+
3036 
+
3037  if (v) {
+
3038  const VertexSet* vset = surf->GetVertexSet();
+
3039  for (int i = 0; i < nverts; i++) {
+
3040  v->x = vset->loc[i].x;
+
3041  v->y = vset->loc[i].y;
+
3042  v->z = vset->loc[i].z;
+
3043 
+
3044  v->diffuse = vset->diffuse[i];
+
3045 
+
3046  v->tu = vset->tu[i];
+
3047  v->tv = vset->tv[i];
+
3048 
+
3049  v++;
+
3050  }
+
3051 
+
3052  surf_data->vertex_buffer->Unlock();
+
3053  }
+
3054  }
+
3055 
+
3056  else if (surface_has_tangent_data) {
+
3057  VideoDX9NormalVertex* v = (VideoDX9NormalVertex*) surf_data->vertex_buffer->Lock(nverts);
+
3058 
+
3059  if (v) {
+
3060  const VertexSet* vset = surf->GetVertexSet();
+
3061  for (int i = 0; i < nverts; i++) {
+
3062  v->x = vset->loc[i].x;
+
3063  v->y = vset->loc[i].y;
+
3064  v->z = vset->loc[i].z;
+
3065 
+
3066  v->nx = vset->nrm[i].x;
+
3067  v->ny = vset->nrm[i].y;
+
3068  v->nz = vset->nrm[i].z;
+
3069 
+
3070  v->t0u = vset->tu[i];
+
3071  v->t0v = vset->tv[i];
+
3072  v->t1u = vset->tu[i];
+
3073  v->t1v = vset->tv[i];
+
3074 
+
3075  v->tx = vset->tangent[i].x;
+
3076  v->ty = vset->tangent[i].y;
+
3077  v->tz = vset->tangent[i].z;
+
3078 
+
3079  v->bx = vset->binormal[i].x;
+
3080  v->by = vset->binormal[i].y;
+
3081  v->bz = vset->binormal[i].z;
+
3082 
+
3083  v++;
+
3084  }
+
3085 
+
3086  surf_data->vertex_buffer->Unlock();
+
3087  }
+
3088  }
+
3089 
+
3090  else {
+
3091  VideoDX9SolidVertex* v = (VideoDX9SolidVertex*) surf_data->vertex_buffer->Lock(nverts);
+
3092 
+
3093  if (v) {
+
3094  const VertexSet* vset = surf->GetVertexSet();
+
3095  for (int i = 0; i < nverts; i++) {
+
3096  v->x = vset->loc[i].x;
+
3097  v->y = vset->loc[i].y;
+
3098  v->z = vset->loc[i].z;
+
3099 
+
3100  v->nx = vset->nrm[i].x;
+
3101  v->ny = vset->nrm[i].y;
+
3102  v->nz = vset->nrm[i].z;
+
3103 
+
3104  v->tu = vset->tu[i];
+
3105  v->tv = vset->tv[i];
+
3106 
+
3107  v++;
+
3108  }
+
3109 
+
3110  surf_data->vertex_buffer->Unlock();
+
3111  }
+
3112  }
+
3113 
+
3114  WORD* indices = surf_data->index_buffer->Lock(nindices);
+
3115 
+
3116  if (indices) {
+
3117  // copy the indices into the locked index buffer
+
3118  WORD* s = indices;
+
3119  Poly* p = surf->GetPolys();
+
3120 
+
3121  for (int i = 0; i < surf->NumPolys(); i++) {
+
3122  if (p->nverts == 3) {
+
3123  *s++ = p->verts[0];
+
3124  *s++ = p->verts[2];
+
3125  *s++ = p->verts[1];
+
3126  }
+
3127  else if (p->nverts == 4) {
+
3128  *s++ = p->verts[0];
+
3129  *s++ = p->verts[2];
+
3130  *s++ = p->verts[1];
+
3131 
+
3132  *s++ = p->verts[0];
+
3133  *s++ = p->verts[3];
+
3134  *s++ = p->verts[2];
+
3135  }
+
3136 
+
3137  p++;
+
3138  }
+
3139 
+
3140  surf_data->index_buffer->Unlock();
+
3141  }
+
3142 
+
3143  surf_data->Validate();
+
3144  }
+
3145 
+
3146  int first_index = 0;
+
3147 
+
3148  ListIter<Segment> seg_iter = surf->GetSegments();
+
3149  while (++seg_iter) {
+
3150  Segment* segment = seg_iter.value();
+
3151 
+
3152  if (!segment->video_data) {
+
3153  VideoDX9SegmentData* seg_data = new(__FILE__,__LINE__) VideoDX9SegmentData;
+
3154 
+
3155  int num_tris = 0;
+
3156  for (int i = 0; i < segment->npolys; i++)
+
3157  num_tris += segment->polys[i].nverts-2;
+
3158 
+
3159  seg_data->first_vert = 0;
+
3160  seg_data->num_verts = surf->NumVerts();
+
3161  seg_data->first_index = first_index;
+
3162  seg_data->num_tris = num_tris;
+
3163 
+
3164  segment->video_data = seg_data;
+
3165 
+
3166  first_index += num_tris * 3;
+
3167  }
+
3168  }
+
3169  }
+
3170 
+
3171  return true;
+
3172 }
+
3173 
+
3174 // +--------------------------------------------------------------------+
+
3175 
+
3176 int
+
3177 VideoDX9::PrepareMaterial(Material* m)
+
3178 {
+
3179  segment_material = m;
+
3180  strategy = 0;
+
3181  passes = 0;
+
3182 
+
3183  if (m) {
+
3184  int max_stages = 1;
+
3185  int max_textures = 1;
+
3186  bool multiply_add = false;
+
3187  bool dotproduct3 = false;
+
3188  bool vertexshader = false;
+
3189  bool pixelshader = false;
+
3190  DWORD vs_version = 0;
+
3191  DWORD ps_version = 0;
+
3192 
+
3193  VideoDX9DeviceInfo* dev_info = dx9enum->GetDeviceInfo(video_settings.GetDeviceType());
+
3194 
+
3195  if (dev_info) {
+
3196  max_stages = (int) dev_info->caps.MaxTextureBlendStages;
+
3197  max_textures = (int) dev_info->caps.MaxSimultaneousTextures;
+
3198  multiply_add = (dev_info->caps.TextureOpCaps & D3DTEXOPCAPS_MULTIPLYADD) ? true : false;
+
3199  dotproduct3 = (dev_info->caps.TextureOpCaps & D3DTEXOPCAPS_DOTPRODUCT3) ? true : false;
+
3200 
+
3201  vs_version = video_settings.enable_vs ? dev_info->caps.VertexShaderVersion : 0;
+
3202  ps_version = video_settings.enable_ps ? dev_info->caps.PixelShaderVersion : 0;
+
3203 
+
3204  vertexshader = vs_version >= D3DVS_VERSION(1,1);
+
3205  pixelshader = ps_version >= D3DPS_VERSION(2,0);
+
3206  }
+
3207 
+
3208  strategy = DX9_STRATEGY_SIMPLE;
+
3209  passes = 1;
+
3210 
+
3211  if (m->tex_alternate) {
+
3212  if (m->tex_detail && max_textures > 2 && max_stages > 4)
+
3213  strategy = DX9_STRATEGY_BLEND_DETAIL;
+
3214 
+
3215  else if (max_textures > 1 && max_stages > 3)
+
3216  strategy = DX9_STRATEGY_BLEND;
+
3217  }
+
3218 
+
3219  else if (m->tex_emissive && (!m->tex_diffuse || m->tex_diffuse == m->tex_emissive)) {
+
3220  strategy = DX9_STRATEGY_GLOW;
+
3221  }
+
3222 
+
3223  else if (IsSpecMapEnabled() && m->tex_specular && !m->tex_emissive) {
+
3224  strategy = DX9_STRATEGY_SPECMAP;
+
3225 
+
3226  if (max_textures < 2 || max_stages < 2 || !multiply_add)
+
3227  passes = 2;
+
3228  }
+
3229 
+
3230  else if ((!IsSpecMapEnabled() || !m->tex_specular) && m->tex_emissive) {
+
3231  strategy = DX9_STRATEGY_EMISSIVE;
+
3232 
+
3233  if (max_textures < 2 || max_stages < 2)
+
3234  passes = 2;
+
3235  }
+
3236 
+
3237  else if (IsSpecMapEnabled() && m->tex_specular && m->tex_emissive) {
+
3238  strategy = DX9_STRATEGY_SPEC_EMISSIVE;
+
3239 
+
3240  if (max_textures < 2 || max_stages < 2)
+
3241  passes = 3;
+
3242 
+
3243  else if (max_textures < 3 || max_stages < 3 || !multiply_add)
+
3244  passes = 2;
+
3245  }
+
3246  }
+
3247 
+
3248  return passes;
+
3249 }
+
3250 
+
3251 bool
+
3252 VideoDX9::SetupPass(int pass)
+
3253 {
+
3254  if (pass < 0 || pass >= passes)
+
3255  return false;
+
3256 
+
3257  if (pass == 0) {
+
3258  D3DMATERIAL9 d3dmtl;
+
3259  IDirect3DTexture9* texture_0 = 0;
+
3260  IDirect3DTexture9* texture_1 = 0;
+
3261  IDirect3DTexture9* texture_2 = 0;
+
3262  Bitmap* tex_bmp_0 = 0;
+
3263  Bitmap* tex_bmp_1 = 0;
+
3264  Bitmap* tex_bmp_2 = 0;
+
3265  ColorValue orig_spec = segment_material->Ks;
+
3266  HRESULT hr = E_FAIL;
+
3267 
+
3268  if (segment_material->tex_specular && passes > 1)
+
3269  segment_material->Ks = Color::Black;
+
3270 
+
3271  CreateD3DMaterial(d3dmtl, *segment_material);
+
3272  segment_material->Ks = orig_spec;
+
3273 
+
3274  hr = d3ddevice->SetMaterial(&d3dmtl);
+
3275 
+
3276  if (strategy == DX9_STRATEGY_SIMPLE) {
+
3277  tex_bmp_0 = segment_material->tex_diffuse;
+
3278  }
+
3279 
+
3280  else if (strategy == DX9_STRATEGY_BLEND) {
+
3281  tex_bmp_0 = segment_material->tex_diffuse;
+
3282  tex_bmp_1 = segment_material->tex_alternate;
+
3283  }
+
3284 
+
3285  else if (strategy == DX9_STRATEGY_BLEND_DETAIL) {
+
3286  tex_bmp_0 = segment_material->tex_diffuse;
+
3287  tex_bmp_1 = segment_material->tex_alternate;
+
3288  tex_bmp_2 = segment_material->tex_detail;
+
3289  }
+
3290 
+
3291  else if (strategy == DX9_STRATEGY_SPECMAP) {
+
3292  if (passes == 1) {
+
3293  tex_bmp_0 = segment_material->tex_diffuse;
+
3294  tex_bmp_1 = segment_material->tex_specular;
+
3295  }
+
3296  else {
+
3297  tex_bmp_0 = segment_material->tex_diffuse;
+
3298  }
+
3299  }
+
3300 
+
3301  else if (strategy == DX9_STRATEGY_EMISSIVE && passes == 1 ||
+
3302  strategy == DX9_STRATEGY_SPEC_EMISSIVE && passes == 2) {
+
3303  if (segment_material->tex_diffuse) {
+
3304  tex_bmp_0 = segment_material->tex_diffuse;
+
3305  tex_bmp_1 = segment_material->tex_emissive;
+
3306  }
+
3307  else {
+
3308  tex_bmp_0 = segment_material->tex_emissive;
+
3309  }
+
3310  }
+
3311 
+
3312  else {
+
3313  tex_bmp_0 = segment_material->tex_emissive;
+
3314  }
+
3315 
+
3316  if (texcache && tex_bmp_0) {
+
3317  texture_0 = texcache->FindTexture(tex_bmp_0);
+
3318 
+
3319  hr = d3ddevice->SetTexture(0, texture_0);
+
3320  current_texture = texture_0;
+
3321 
+
3322  if (tex_bmp_1) {
+
3323  texture_1 = texcache->FindTexture(tex_bmp_1);
+
3324  hr = d3ddevice->SetTexture(1, texture_1);
+
3325 
+
3326  if (tex_bmp_2) {
+
3327  texture_2 = texcache->FindTexture(tex_bmp_2);
+
3328  hr = d3ddevice->SetTexture(2, texture_2);
+
3329  }
+
3330  }
+
3331  }
+
3332  else {
+
3333  hr = d3ddevice->SetTexture(0, 0);
+
3334  current_texture = 0;
+
3335  }
+
3336 
+
3337  SetBlendType(segment_material->blend);
+
3338 
+
3339  if (texture_0 && texture_1 && strategy == DX9_STRATEGY_BLEND) {
+
3340  d3ddevice->SetSamplerState(1, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
+
3341  d3ddevice->SetSamplerState(1, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
+
3342  d3ddevice->SetSamplerState(1, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);
+
3343 
+
3344  d3ddevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
+
3345  d3ddevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
+
3346  d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
+
3347  d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE);
+
3348 
+
3349  d3ddevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_BLENDCURRENTALPHA);
+
3350  d3ddevice->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_CURRENT);
+
3351  d3ddevice->SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_TEXTURE);
+
3352  d3ddevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
+
3353  d3ddevice->SetTextureStageState(1, D3DTSS_ALPHAARG1, D3DTA_CURRENT);
+
3354  d3ddevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 0);
+
3355 
+
3356  d3ddevice->SetTextureStageState(2, D3DTSS_COLOROP, D3DTOP_MODULATE);
+
3357  d3ddevice->SetTextureStageState(2, D3DTSS_COLORARG1, D3DTA_CURRENT);
+
3358  d3ddevice->SetTextureStageState(2, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
+
3359  d3ddevice->SetTextureStageState(2, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
+
3360  d3ddevice->SetTextureStageState(2, D3DTSS_ALPHAARG1, D3DTA_CURRENT);
+
3361 
+
3362  d3ddevice->SetTextureStageState(3, D3DTSS_COLOROP, D3DTOP_DISABLE);
+
3363  }
+
3364 
+
3365  else if (texture_0 && texture_1 && texture_2 && strategy == DX9_STRATEGY_BLEND_DETAIL) {
+
3366  d3ddevice->SetSamplerState(1, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
+
3367  d3ddevice->SetSamplerState(1, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
+
3368  d3ddevice->SetSamplerState(1, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);
+
3369  d3ddevice->SetSamplerState(2, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
+
3370  d3ddevice->SetSamplerState(2, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
+
3371  d3ddevice->SetSamplerState(2, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);
+
3372 
+
3373  d3ddevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
+
3374  d3ddevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
+
3375  d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
+
3376  d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE);
+
3377  d3ddevice->SetTextureStageState(0, D3DTSS_TEXCOORDINDEX, 0);
+
3378 
+
3379  d3ddevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_BLENDCURRENTALPHA);
+
3380  d3ddevice->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_CURRENT);
+
3381  d3ddevice->SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_TEXTURE);
+
3382  d3ddevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
+
3383  d3ddevice->SetTextureStageState(1, D3DTSS_ALPHAARG1, D3DTA_CURRENT);
+
3384  d3ddevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 0);
+
3385 
+
3386  d3ddevice->SetTextureStageState(2, D3DTSS_COLOROP, D3DTOP_BLENDTEXTUREALPHA);
+
3387  d3ddevice->SetTextureStageState(2, D3DTSS_COLORARG1, D3DTA_TEXTURE);
+
3388  d3ddevice->SetTextureStageState(2, D3DTSS_COLORARG2, D3DTA_CURRENT);
+
3389  d3ddevice->SetTextureStageState(2, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
+
3390  d3ddevice->SetTextureStageState(2, D3DTSS_ALPHAARG1, D3DTA_CURRENT);
+
3391  d3ddevice->SetTextureStageState(2, D3DTSS_TEXCOORDINDEX, 1);
+
3392 
+
3393  d3ddevice->SetTextureStageState(3, D3DTSS_COLOROP, D3DTOP_MODULATE);
+
3394  d3ddevice->SetTextureStageState(3, D3DTSS_COLORARG1, D3DTA_CURRENT);
+
3395  d3ddevice->SetTextureStageState(3, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
+
3396  d3ddevice->SetTextureStageState(3, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
+
3397  d3ddevice->SetTextureStageState(3, D3DTSS_ALPHAARG1, D3DTA_CURRENT);
+
3398  }
+
3399 
+
3400  else if (texture_0 && strategy == DX9_STRATEGY_GLOW) {
+
3401  d3ddevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
+
3402  d3ddevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
+
3403  d3ddevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_CURRENT);
+
3404  d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
+
3405  d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
+
3406  }
+
3407 
+
3408  else if (texture_0) {
+
3409  d3ddevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
+
3410  d3ddevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
+
3411  d3ddevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_CURRENT);
+
3412  d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
+
3413  d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
+
3414  }
+
3415 
+
3416  if (texture_1 && strategy == DX9_STRATEGY_SPECMAP) {
+
3417  d3ddevice->SetSamplerState(1, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
+
3418  d3ddevice->SetSamplerState(1, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
+
3419  d3ddevice->SetSamplerState(1, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);
+
3420 
+
3421  d3ddevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 0);
+
3422  d3ddevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_MULTIPLYADD);
+
3423  d3ddevice->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_TEXTURE);
+
3424  d3ddevice->SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_SPECULAR);
+
3425  d3ddevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
+
3426  d3ddevice->SetTextureStageState(1, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
+
3427  }
+
3428 
+
3429  else if (texture_1 && strategy == DX9_STRATEGY_EMISSIVE) {
+
3430  d3ddevice->SetSamplerState(1, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
+
3431  d3ddevice->SetSamplerState(1, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
+
3432  d3ddevice->SetSamplerState(1, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);
+
3433 
+
3434  d3ddevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 0);
+
3435  d3ddevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_ADD);
+
3436  d3ddevice->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_TEXTURE);
+
3437  d3ddevice->SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_CURRENT);
+
3438  d3ddevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
+
3439  d3ddevice->SetTextureStageState(1, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
+
3440  }
+
3441 
+
3442  else if (texture_1 && strategy == DX9_STRATEGY_SPEC_EMISSIVE) {
+
3443  d3ddevice->SetSamplerState(1, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
+
3444  d3ddevice->SetSamplerState(1, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
+
3445  d3ddevice->SetSamplerState(1, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);
+
3446 
+
3447  d3ddevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 0);
+
3448  d3ddevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_ADD);
+
3449  d3ddevice->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_TEXTURE);
+
3450  d3ddevice->SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_CURRENT);
+
3451  d3ddevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
+
3452  d3ddevice->SetTextureStageState(1, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
+
3453  }
+
3454 
+
3455  else if (strategy < DX9_STRATEGY_BLEND) {
+
3456  d3ddevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
+
3457  }
+
3458  }
+
3459 
+
3460  else if (pass == 1) {
+
3461  D3DMATERIAL9 d3dmtl;
+
3462  IDirect3DTexture9* texture = 0;
+
3463  Bitmap* tex_bmp = 0;
+
3464  ColorValue orig_Ka = segment_material->Ka;
+
3465  ColorValue orig_Kd = segment_material->Kd;
+
3466  HRESULT hr = E_FAIL;
+
3467 
+
3468  if (segment_material->tex_specular) {
+
3469  segment_material->Ka = Color::Black;
+
3470  segment_material->Kd = Color::Black;
+
3471  }
+
3472 
+
3473  CreateD3DMaterial(d3dmtl, *segment_material);
+
3474 
+
3475  segment_material->Ka = orig_Ka;
+
3476  segment_material->Kd = orig_Kd;
+
3477 
+
3478  hr = d3ddevice->SetMaterial(&d3dmtl);
+
3479 
+
3480  if (strategy == DX9_STRATEGY_SPECMAP ||
+
3481  strategy == DX9_STRATEGY_SPEC_EMISSIVE) {
+
3482  tex_bmp = segment_material->tex_specular;
+
3483  d3ddevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
+
3484  d3ddevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
+
3485  d3ddevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_SPECULAR);
+
3486  }
+
3487 
+
3488  else if (strategy == DX9_STRATEGY_EMISSIVE) {
+
3489  tex_bmp = segment_material->tex_emissive;
+
3490  d3ddevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
+
3491  d3ddevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
+
3492  }
+
3493 
+
3494  d3ddevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
+
3495 
+
3496  if (texcache && tex_bmp) {
+
3497  texture = texcache->FindTexture(tex_bmp);
+
3498  hr = d3ddevice->SetTexture(0, texture);
+
3499  current_texture = texture;
+
3500 
+ +
3502  }
+
3503  }
+
3504 
+
3505  if (render_state[STENCIL_ENABLE]) {
+
3506  d3ddevice->SetRenderState(D3DRS_STENCILENABLE, TRUE);
+
3507  d3ddevice->SetRenderState(D3DRS_STENCILREF, 0x01);
+
3508  d3ddevice->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_GREATER);
+
3509  }
+
3510  else {
+
3511  d3ddevice->SetRenderState(D3DRS_STENCILENABLE, FALSE);
+
3512  }
+
3513 
+
3514  if (render_state[LIGHTING_PASS] > 0) {
+ + +
3517  }
+
3518 
+
3519  return true;
+
3520 }
+
3521 
+
3522 
+
3523 // +--------------------------------------------------------------------+
+
3524 
+
3525 void
+
3526 VideoDX9Error(const char* msg, HRESULT err)
+
3527 {
+
3528  Print(" VideoDX9: %s. [%s]\n", msg, D3DErrStr(err));
+
3529 }
+
3530 
+
3531 char* D3DErrStr(HRESULT hr)
+
3532 {
+
3533  static char errstrbuf[128];
+
3534 
+
3535  switch (hr) {
+
3536  default:
+
3537  sprintf_s(errstrbuf, "Unrecognized error value = %08x.", hr);
+
3538  return errstrbuf;
+
3539 
+
3540  case D3D_OK:
+
3541  return "No error.";
+
3542 
+
3543  case D3DERR_WRONGTEXTUREFORMAT:
+
3544  return "Wrong texture format.";
+
3545 
+
3546  case D3DERR_UNSUPPORTEDCOLOROPERATION:
+
3547  return "Unsupported color operation.";
+
3548 
+
3549  case D3DERR_UNSUPPORTEDCOLORARG:
+
3550  return "Unsupported color argument.";
+
3551 
+
3552  case D3DERR_UNSUPPORTEDALPHAOPERATION:
+
3553  return "Unsupported alpha operation.";
+
3554 
+
3555  case D3DERR_UNSUPPORTEDALPHAARG:
+
3556  return "Unsupported alpha argument.";
+
3557 
+
3558  case D3DERR_TOOMANYOPERATIONS:
+
3559  return "Too many operations.";
+
3560 
+
3561  case D3DERR_CONFLICTINGTEXTUREFILTER:
+
3562  return "Conflicting texture filter.";
+
3563 
+
3564  case D3DERR_UNSUPPORTEDFACTORVALUE:
+
3565  return "Unsupported factor value.";
+
3566 
+
3567  case D3DERR_CONFLICTINGRENDERSTATE:
+
3568  return "Conflicting render state.";
+
3569 
+
3570  case D3DERR_UNSUPPORTEDTEXTUREFILTER:
+
3571  return "Unsupported texture filter.";
+
3572 
+
3573  case D3DERR_CONFLICTINGTEXTUREPALETTE:
+
3574  return "Conflicting texture palette.";
+
3575 
+
3576  case D3DERR_DRIVERINTERNALERROR:
+
3577  return "Driver internal error.";
+
3578 
+
3579 
+
3580  case D3DERR_NOTFOUND:
+
3581  return "Resource was not found.";
+
3582 
+
3583  case D3DERR_MOREDATA:
+
3584  return "More data?";
+
3585 
+
3586  case D3DERR_DEVICELOST:
+
3587  return "Device lost.";
+
3588 
+
3589  case D3DERR_DEVICENOTRESET:
+
3590  return "Device is not reset.";
+
3591 
+
3592  case D3DERR_NOTAVAILABLE:
+
3593  return "Not available.";
+
3594 
+
3595  case D3DERR_OUTOFVIDEOMEMORY:
+
3596  return "Out of video memory.";
+
3597 
+
3598  case E_OUTOFMEMORY:
+
3599  return "Out of system memory.";
+
3600 
+
3601  case D3DERR_INVALIDDEVICE:
+
3602  return "Invalid device selection.";
+
3603 
+
3604  case D3DERR_INVALIDCALL:
+
3605  return "Invalid call or parameter.";
+
3606 
+
3607  case D3DERR_DRIVERINVALIDCALL:
+
3608  return "Driver invalid call.";
+
3609 
+
3610  case D3DERR_WASSTILLDRAWING:
+
3611  return "The device was still drawing.";
+
3612 
+
3613  case D3DOK_NOAUTOGEN:
+
3614  return "Autogeneration is not supported by this device.";
+
3615 
+
3616  }
+
3617 }
+
3618 
+
+
+ + + + -- cgit v1.1