Программирование под стереоочки (часть 2).

В первой части заметки рассказывалось о том, как имея две части стереопары, предъявить их наблюдателю, надевшему стереоочки, в последовательных кадрах таким образом, чтобы возник стереоэффект. Такая задача возникает, например, при разработке просмотрщика стереоизображений.

В данной части коротко рассмотрим программную реализацию несколько иной задачи – как предъявить наблюдателю, надевшему стереоочки, одно изображение трехмерной сцены таким образом, чтобы возник стереоэффект. Такая задача возникает, например, при разработке игр, призванных поддерживать стереорежимы. Поэтому для синтеза изображений необходимо использовать программные средства, позволяющие в зависимости от видеокарты и настроек ее драйвера успешно воспроизводить одну и ту же сцену как в стерео-, так и в обычном видеорежиме. Одним из таких программных средств, доступных разработчику, являются библиотеки DirectX и, в частности, модуль DirectXGraphics. Подробные сведения об использовании функций DirectX содержатся в многочисленных статьях, однако вопрос поддержки стереорежима в них не рассматривается. При написании данного примера были использованы главы книги, выложенные по адресу http://www.softera.ru/literature/directx/1/Nn.htm, где Nn – номер главы.

Важные моменты синтеза трехмерной объемной сцены с помощью DirectX сводятся к следующему:

  1. При описании вершин графических примитивов необходимо задействовать третью координату объектов, что сводится к отказу от системы координат, связанной с окном приложения (определяемой константой DSDFVF_XYZRHW).
  2. При создании окна приложения необходимо использовать полноэкранный режим.
  3. В настройках видеодрайвера на вкладке, посвященной стереорежиму, необходимо установить поддержку DirectX. Например, для видеокарты ASUS V7700 Deluxe на вкладке ”Direct3d VR” на панели “эффект виртуальной реальности” следует установить галочку “включить стереорежим”.

Учитывая вышесказанное, приведем текст программы на Delphi для рисования объемных красно-сине-зеленого треугольника и желтого квадрата. Фигуры вращаются вокруг своих осей при нажатии на любую кнопку.

unit SimpleStereo;

interface

uses

Windows, Messages, SysUtils, Classes, Graphics, Controls,
Forms, Dialogs,
DirectXGraphics, DxgUtils, StdCtrls;

type

TCUSTOMVERTEX = packed record

X, Y, Z: Single;//!! не используем RHW
Color: DWord;

end;

TForm1 = class(TForm)

procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure FormPaint(Sender: TObject);
procedure InitPoint;
procedure FormKeyPress(Sender: TObject; var Key: Char);

public

Angle: Real;
Vertices: array [0..6] of TCUSTOMVERTEX;
g_pD3D: IDirect3D8;
g_device: IDirect3DDevice8;
FD3DVB: IDIRECT3DVERTEXBUFFER8;

end;

const

.//!! Не используем константу DSDFVF_XYZRHW
D3DFVF_COSTOMVERTEX = D3DFVF_XYZ
or D3DFVF_DIFFUSE;
fmtFullscreenArray : array [0..4] of DWORD =
(D3DFMT_R5G6B5, D3DFMT_X1R5G5B5, D3DFMT_A1R5G5B5, D3DFMT_X8R8G8B8,
D3DFMT_A8R8G8B8);

var

Form1: TForm1;// Form1 – “пустая” форма, поэтому dfm-файл приводить нецелесообразно

implementation

{$R *.DFM}

procedure TForm1.FormCreate(Sender: TObject);

var

d3dpp: TD3DPresent_Parameters;
iFmt: Integer;
FDSDfmtFullscreen: DWord;

begin

g_pD3D := Direct3DCreate8(D3D_SDK_VERSION);
if g_pD3D = nil then

exit;

for iFmt := 0 to High(fmtFullscreenArray) do

begin

if SUCCEEDED(g_pD3D.CheckDeviceType(D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL,fmtFullscreenArray[iFmt], fmtFullscreenArray[iFmt], False)) then

begin

FDSDfmtFullscreen := fmtFullscreenArray[iFmt];
Break; // Найден подходящий

end;

end;

ZeroMemory(@d3dpp, sizeof(d3dpp));
d3dpp.Windowed := False;
//!!полноэкранный режим
d3dpp.BackBufferFormat := FDSDfmtFullscreen;
d3dpp.BackBufferWidth := 800;
d3dpp.BackBufferHeight := 600;
d3dpp.SwapEffect := D3DSWAPEFFECT_DISCARD;
if FAILED(g_pD3D.CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, Handle,D3DCREATE_HARDWARE_VERTEXPROCESSING, d3dpp, g_device)) then

exit;

InitPoint;

end;

 

procedure TForm1.FormDestroy(Sender: TObject);

begin

g_device := nil;
g_pD3D := nil;

end;

 

procedure TForm1.FormPaint(Sender: TObject);

var

matRotate, matTranslate, matView, matProj : TD3DMatrix; //Матрицы 4x4

begin

g_device.Clear(0, nil, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0, 0);
g_device.BeginScene();
g_device.SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
g_device.SetRenderState(D3DRS_LIGHTING, DWORD(False));
SetRotateXMatrix(matRotate, Angle);
SetTranslateMatrix(matTranslate, -1.0, 2.0, 0.0);// Треугольник сдвигается на единицу влево и на 2 ед. вверх
g_device.SetTransform(D3DTS_WORLD, MatrixMul(matRotate, matTranslate));// Устанавливаем мировую матрицу трансформаций
g_device.DrawPrimitive(D3DPT_TRIANGLELIST, 0, 1);
SetRotateYMatrix(matRotate, 2 * Angle);
SetTranslateMatrix(matTranslate, 1.0, 2.0, 0.0);// Квадрат сдвигается на единицу вправо и на 2 ед. вверх
g_device.SetTransform(D3DTS_WORLD, MatrixMul(matTranslate, matRotate)); // Матрица трансформаций для квадрата
g_device.DrawPrimitive(D3DPT_TRIANGLESTRIP, 3, 2);
SetViewMatrix(matView, D3DVector(0, 0, 5), D3DVector(0, 0, 0), D3DVector(0, 1, 0)); // Устанавливаем видовую матрицу
g_device.SetTransform(D3DTS_VIEW, matView);
SetProjectionMatrix(matProj, 1, 1, 1, 10); // Задаем матрицу проекций
g_device.SetTransform(D3DTS_PROJECTION, matProj);// Устанавливаем матрицу проекций
g_device.EndScene();
g_device.Present(nil, nil, 0, nil);

end;

 

procedure TForm1.InitPoint;

var

pVertices : PByte;

begin

Angle := 0;
Vertices[0].X := 0.0; // Первая вершина треугольника
Vertices[0].Y := 1.0;
Vertices[0].Z := 0.0;
Vertices[0].Color := $00FF0000;
Vertices[1].X := 1.0; // Вторая вершина треугольника
Vertices[1].Y := -1.0;
Vertices[1].Z := 0.0;
Vertices[1].Color := $0000FF00;
Vertices[2].X := -1.0; // Третья вершина треугольника
Vertices[2].Y := -1.0;
Vertices[2].Z := 0.0;
Vertices[2].Color := $000000FF;
Vertices[3].X := -1.0; // Первая вершина квадрата
Vertices[3].Y := -1.0;
Vertices[3].Z := 0.0;
Vertices[3].Color := $00FFFF00;
Vertices[4].X := -1.0; // Вторая вершина квадрата
Vertices[4].Y := 1.0;
Vertices[4].Z := 0.0;
Vertices[4].Color := $00FFFF00;
Vertices[5].X := 1.0; // Третья вершина квадрата
Vertices[5].Y := -1.0;
Vertices[5].Z := 0.0;
Vertices[5].Color := $00FFFF00;
Vertices[6].X := 1.0; // Четвертая вершина квадрата
Vertices[6].Y := 1.0;
Vertices[6].Z := 0.0;
Vertices[6].Color := $00FFFF00;
g_device.CreateVertexBuffer(SizeOf(Vertices), D3DUSAGE_WRITEONLY, D3DFVF_COSTOMVERTEX, D3DPOOL_DEFAULT, FD3DVB);
FD3DVB.Lock(0, SizeOf(Vertices), pVertices, 0);
Move(Vertices, pVertices^, SizeOf(Vertices));
FD3DVB.Unlock();
g_Device.SetStreamSource(0, FD3DVB, SizeOf(TCUSTOMVERTEX));
g_device.SetVertexShader(D3DFVF_COSTOMVERTEX);

end;

procedure TForm1.FormKeyPress(Sender: TObject; var Key: Char);

begin

Angle := Angle + 0.5;
SendMessage(Self.HANDLE, WM_PAINT, 0, 0);

end;

end.



Сайт управляется системой uCoz