-
Читаю туториал по Direct3D от мелкомягкого. Чтобы не дай Бог чего-нибудь наперекосяк не пошло (с этим зверем никогда не работал), делаю все так, как там сказано. Ну, иногда переписываю часть кода из примеров, чтобы все работало, где-то экспериментирую, сравниваю с OpenGL, но это мелочи. Пользуюсь джедаевскими заголовками. В-общем, кто-нибудь может мне объяснить, почему эти прямоугольники не могут вращаться как им положено? program Project1;
uses
Windows,
Messages,
Direct3D9,
D3DX9;
const
D3DFVF_CUSTOMVERTEX = D3DFVF_XYZ or D3DFVF_DIFFUSE;
type
HINST = Cardinal;
Float = Single;
CUSTOMVERTEX = record
x, y, z: Float;
color: DWord;
end;
var
g_hInst: HINST = 0;
g_hWnd: HWND = 0;
g_pD3D: IDirect3D9;
g_pd3dDevice: IDirect3DDevice9;
g_pVB: IDirect3DVertexBuffer9;
vertices: Array[0..11] of CUSTOMVERTEX =
((x: 0.0; y: 0.0; z: 0.0; color: $ffff0000),
(x: 1.0; y: 0.0; z: 0.0; color: $ff0000ff),
(x: 1.0; y: 1.0; z: 0.0; color: $ffffffff),
(x: 1.0; y: 1.0; z: 0.0; color: $ffff0000),
(x: 0.0; y: 1.0; z: 0.0; color: $ff0000ff),
(x: 0.0; y: 0.0; z: 0.0; color: $ffffffff),
(x: 0.0; y: 0.0; z: 1.0; color: $ffff0000),
(x: 1.0; y: 0.0; z: 1.0; color: $ff0000ff),
(x: 1.0; y: 1.0; z: 1.0; color: $ffffffff),
(x: 1.0; y: 1.0; z: 1.0; color: $ffff0000),
(x: 0.0; y: 1.0; z: 1.0; color: $ff0000ff),
(x: 0.0; y: 0.0; z: 1.0; color: $ffffffff));
procedure Render;
var
matWorld: TD3DXMATRIXA16;
matView: TD3DXMATRIXA16;
matProj: TD3DXMATRIXA16;
iTime: Integer;
fAngle: Float;
vEyePt, vLookatPt, vUpVec: TD3DXVECTOR3;
begin
g_pd3dDevice.Clear(0, 0, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0, 0);
g_pd3dDevice.BeginScene;
iTime := GetTickCount();
fAngle := iTime * (1.0 * D3DX_PI) / 1000.0;
D3DXMatrixRotationY( matWorld, fAngle );
g_pd3dDevice.SetTransform( D3DTS_WORLD, matWorld );
vEyePt := D3DXVECTOR3( 0.0, 3.0,-5.0 );
vLookatPt := D3DXVECTOR3( 0.0, 0.0, 0.0 );
vUpVec := D3DXVECTOR3( 0.0, 1.0, 0.0 );
D3DXMatrixLookAtLH( matView, vEyePt, vLookatPt, vUpVec );
g_pd3dDevice.SetTransform( D3DTS_VIEW, matView );
D3DXMatrixPerspectiveFovLH( matProj, D3DX_PI/4, 1.0, 1.0, 100.0 );
g_pd3dDevice.SetTransform( D3DTS_PROJECTION, matProj );
g_pd3dDevice.SetStreamSource( 0, g_pVB, 0, sizeof(CUSTOMVERTEX) );
g_pd3dDevice.SetFVF( D3DFVF_CUSTOMVERTEX );
g_pd3dDevice.DrawPrimitive( D3DPT_TRIANGLELIST, 0, Length(vertices) div 3 );
g_pd3dDevice.EndScene;
g_pd3dDevice.Present(nil, nil, 0, nil);
end;
procedure Cleanup;
begin
if g_pVB <> nil then begin
g_pVB._Release;
g_pVB := nil;
end;
if g_pd3dDevice <> nil then begin
g_pd3dDevice._Release;
g_pd3dDevice := nil;
end;
if g_pD3D <> nil then begin
g_pD3D._Release;
g_pD3D := nil;
end;
end;
function WndProc(hWnd: HWND; Message: UINT; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
begin
case Message of
WM_PAINT: begin
Render;
end;
WM_DESTROY: begin
PostQuitMessage(0);
Cleanup;
end;
else begin
Result := DefWindowProc(hWnd, message, wParam, lParam);
Exit;
end;
end;
Result := 0;
end;
function InitWindow(hInstance: HINST; nCmdShow: Integer): HRESULT;
var
wcex: WNDCLASSEX;
rc: TRect;
begin
Result := E_FAIL;
wcex.cbSize := sizeof(WNDCLASSEX);
wcex.style := CS_HREDRAW or CS_VREDRAW;
wcex.lpfnWndProc := @WndProc;
wcex.cbClsExtra := 0;
wcex.cbWndExtra := 0;
wcex.hInstance := hInstance;
wcex.hIcon := LoadIcon(0, IDI_APPLICATION);
wcex.hCursor := LoadCursor(0, IDC_ARROW);
wcex.hbrBackground := COLOR_WINDOW+1;
wcex.lpszMenuName := 0;
wcex.lpszClassName := 'TutorialWindowClass';
wcex.hIconSm := LoadIcon(0, IDI_APPLICATION);
if RegisterClassEx(wcex) = 0 then Exit;
g_hInst := hInstance;
rc.Left := 0;
rc.Top := 0;
rc.Right := 640;
rc.Bottom := 480;
AdjustWindowRect( rc, WS_OVERLAPPEDWINDOW, FALSE );
g_hWnd := CreateWindow( 'TutorialWindowClass', 'Direct3D 10 Tutorial 0: Setting Up Window', WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, rc.right - rc.left, rc.bottom - rc.top, 0, 0, hInstance, 0);
if g_hWnd = 0 then Exit;
ShowWindow( g_hWnd, nCmdShow );
Result := S_OK;
end;
function InitD3D: HRESULT;
var
d3dpp: D3DPRESENT_PARAMETERS;
pVertices: Pointer;
begin
Result := E_FAIL;
g_pD3D := Direct3DCreate9(D3D_SDK_VERSION);
if g_pD3D = nil then Exit;
ZeroMemory(@d3dpp, SizeOf(d3dpp));
d3dpp.Windowed := TRUE;
d3dpp.SwapEffect := D3DSWAPEFFECT_DISCARD;
d3dpp.BackBufferFormat := D3DFMT_UNKNOWN;
if( FAILED( g_pD3D.CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, g_hWnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
@d3dpp, g_pd3dDevice ) ) ) then Exit;
g_pd3dDevice.SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );
g_pd3dDevice.SetRenderState( D3DRS_LIGHTING, iFalse );
if FAILED( g_pd3dDevice.CreateVertexBuffer( sizeof(vertices),
0, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, g_pVB, 0 ) ) then Exit;
if FAILED( g_pVB.Lock( 0, sizeof(vertices), pVertices, 0 ) ) then Exit;
CopyMemory(pVertices, @vertices, sizeof(vertices));
g_pVB.Unlock;
Result := S_OK;
end;
function wWinMain(hInstance, hPrevInstance: HINST; lpCmdLine: PChar; nCmdShow: Integer): Integer; stdcall;
var
msg: tagMSG;
begin
Result := 0;
if FAILED( InitWindow( hInstance, nCmdShow ) ) then Exit;
if FAILED( InitD3D ) then Exit;
while( GetMessage( msg, 0, 0, 0 ) ) do begin
TranslateMessage( msg );
DispatchMessage( msg );
end;
Result := msg.wParam;
end;
begin
wWinMain(hInstance, hPrevInst, CmdLine, CmdShow);
end.
-
Если нужно, чтобы они вращались симметрично - вычесть 0.5 из всех координат, т.к. матрица трансформации поворачивает относительно центра (0,0,0). Можно включить перемещение в саму матрицу.
-
Если Сишный код не проблема - много хороших туториалов тут: http://www.codesampler.com/dx9src.htmНо > почему эти прямоугольники не могут вращаться как им положено?А как положено ? =) То есть - как они должны вращаться ? З.Ы. g_pd3dDevice._Release; и вообще _Release вызывать не надо.
-
Пара примеров:
program dx9_vertex_data;
uses
Windows,
Messages,
MMSystem,
Direct3D9,
D3DX9;
type
TVertex = record
x, y, z : Single;
tu, tv : Single
end;
const
FVF_Flags = D3DFVF_XYZ or D3DFVF_TEX1;
var
g_hWnd : THandle = 0;
g_pD3D : IDirect3D9 = nil;
g_pd3dDevice : IDirect3DDevice9 = nil;
g_pVertexBuffer : IDirect3DVertexBuffer9 = nil;
g_pTexture : IDirect3DTexture9 = nil;
g_fElapsedTime : Single = 0;
g_dCurrentTime : Double = 0;
g_dLastTime : Double = 0;
g_fXrot : Single = 0.0;
g_fYrot : Single = 0.0;
g_fZrot : Single = 0.0;
winClass : WNDCLASSEX;
uMsg : MSG;
g_cubeVertices : array[0..23] of TVertex =
((x:-1.0; y: 1.0; z:-1.0; tu: 0.0; tv: 0.0),
(x: 1.0; y: 1.0; z:-1.0; tu: 1.0; tv: 0.0),
(x:-1.0; y:-1.0; z:-1.0; tu: 0.0; tv: 1.0),
(x: 1.0; y:-1.0; z:-1.0; tu: 1.0; tv: 1.0),
(x:-1.0; y: 1.0; z: 1.0; tu: 1.0; tv: 0.0),
(x:-1.0; y:-1.0; z: 1.0; tu: 1.0; tv: 1.0),
(x: 1.0; y: 1.0; z: 1.0; tu: 0.0; tv: 0.0),
(x: 1.0; y:-1.0; z: 1.0; tu: 0.0; tv: 1.0),
(x:-1.0; y: 1.0; z: 1.0; tu: 0.0; tv: 0.0),
(x: 1.0; y: 1.0; z: 1.0; tu: 1.0; tv: 0.0),
(x:-1.0; y: 1.0; z:-1.0; tu: 0.0; tv: 1.0),
(x: 1.0; y: 1.0; z:-1.0; tu: 1.0; tv: 1.0),
(x:-1.0; y:-1.0; z: 1.0; tu: 0.0; tv: 0.0),
(x:-1.0; y:-1.0; z:-1.0; tu: 1.0; tv: 0.0),
(x: 1.0; y:-1.0; z: 1.0; tu: 0.0; tv: 1.0),
(x: 1.0; y:-1.0; z:-1.0; tu: 1.0; tv: 1.0),
(x: 1.0; y: 1.0; z:-1.0; tu: 0.0; tv: 0.0),
(x: 1.0; y: 1.0; z: 1.0; tu: 1.0; tv: 0.0),
(x: 1.0; y:-1.0; z:-1.0; tu: 0.0; tv: 1.0),
(x: 1.0; y:-1.0; z: 1.0; tu: 1.0; tv: 1.0),
(x:-1.0; y: 1.0; z:-1.0; tu: 1.0; tv: 0.0),
(x:-1.0; y:-1.0; z:-1.0; tu: 1.0; tv: 1.0),
(x:-1.0; y: 1.0; z: 1.0; tu: 0.0; tv: 0.0),
(x:-1.0; y:-1.0; z: 1.0; tu: 0.0; tv: 1.0));
//-----------------------------------------------------------------------------
function WindowProc(ihwnd: THandle; uMsg: Longword; wParam: Longint; lParam: Longint): Longint; stdcall;
begin
WindowProc := 0;
case uMsg of
WM_KEYDOWN: begin
if wParam = VK_ESCAPE then PostQuitMessage(0);
end;
WM_CLOSE: PostQuitMessage(0);
WM_DESTROY: PostQuitMessage(0);
else WindowProc := DefWindowProc(ihwnd, uMsg, wParam, lParam);
end;
end;
//-----------------------------------------------------------------------------
// Name: LoadTexture()
// Desc:
//-----------------------------------------------------------------------------
procedure LoadTexture;
begin
g_pTexture := nil;
D3DXCreateTextureFromFile(g_pd3dDevice, 'test.bmp', g_pTexture);
g_pd3dDevice.SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
g_pd3dDevice.SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
end;
procedure Init;
var
d3ddm : TD3DDisplayMode;
d3dpp : TD3DPresentParameters;
matProj : TD3DMatrix;
pVertices : Pointer;
begin
g_pD3D := Direct3DCreate9(D3D_SDK_VERSION);
g_pD3D.GetAdapterDisplayMode(D3DADAPTER_DEFAULT,
d3ddm);
ZeroMemory(@d3dpp, SizeOf(TD3DPresentParameters));
with d3dpp do
begin
Windowed := True;
SwapEffect := D3DSWAPEFFECT_DISCARD;
BackBufferFormat := d3ddm.Format;
EnableAutoDepthStencil := True;
AutoDepthStencilFormat := D3DFMT_D16;
PresentationInterval := D3DPRESENT_INTERVAL_IMMEDIATE;
end;
g_pD3D.CreateDevice(D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL,
g_hWnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
@d3dpp,
g_pd3dDevice);
LoadTexture;
g_pd3dDevice.CreateVertexBuffer(24 * SizeOf(TVertex),
0,
FVF_Flags,
D3DPOOL_DEFAULT,
g_pVertexBuffer,
nil);
pVertices := nil;
g_pVertexBuffer.Lock(0, SizeOf(g_cubeVertices), pVertices, 0);
Move(g_cubeVertices, pVertices^, SizeOf(g_cubeVertices));
g_pVertexBuffer.Unlock;
g_pd3dDevice.SetRenderState(D3DRS_LIGHTING, iFalse);
g_pd3dDevice.SetRenderState(D3DRS_ZENABLE, iTrue);
D3DXMatrixPerspectiveFovLH(matProj,
D3DXToRadian(45.0),
(640 / 480),
0.1,
100.0);
g_pd3dDevice.SetTransform(D3DTS_PROJECTION, matProj);
end;
procedure ShutDown;
begin
if Assigned(g_pTexture) then
begin
g_pTexture._Release;
g_pTexture := nil;
end;
if Assigned(g_pVertexBuffer) then
begin
g_pVertexBuffer._Release;
g_pVertexBuffer := nil;
end;
if Assigned(g_pd3dDevice) then
begin
g_pd3dDevice._Release;
g_pd3dDevice := nil;
end;
if Assigned(g_pD3D) then
begin
g_pD3D._Release;
g_pD3D := nil;
end;
end;
-
продолжение кода...
procedure Render;
var
matWorld : TD3DMatrix;
matTrans : TD3DMatrix;
matRot : TD3DMatrix;
begin
if g_pd3dDevice = nil then Exit;
g_pd3dDevice.Clear(0,
nil,
D3DCLEAR_TARGET or D3DCLEAR_ZBUFFER,
D3DCOLOR_COLORVALUE(0.0, 0.0, 0.0, 1.0),
1.0,
0);
g_fXrot := g_fXrot + (10.1 * g_fElapsedTime);
g_fYrot := g_fYrot + (10.2 * g_fElapsedTime);
g_fZrot := g_fZrot + (10.3 * g_fElapsedTime);
D3DXMatrixTranslation(matTrans, 0.0, 0.0, 5.0);
D3DXMatrixRotationYawPitchRoll(matRot,
D3DXToRadian(g_fXrot),
D3DXToRadian(g_fYrot),
D3DXToRadian(g_fZrot));
D3DXMatrixMultiply(matWorld, matRot, matTrans);
g_pd3dDevice.SetTransform(D3DTS_WORLD, matWorld);
g_pd3dDevice.BeginScene;
g_pd3dDevice.SetTexture(0, g_pTexture);
g_pd3dDevice.SetStreamSource(0, g_pVertexBuffer, 0, SizeOf(TVertex));
g_pd3dDevice.SetFVF(FVF_Flags);
g_pd3dDevice.DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2 );
g_pd3dDevice.DrawPrimitive(D3DPT_TRIANGLESTRIP, 4, 2 );
g_pd3dDevice.DrawPrimitive(D3DPT_TRIANGLESTRIP, 8, 2 );
g_pd3dDevice.DrawPrimitive(D3DPT_TRIANGLESTRIP, 12, 2 );
g_pd3dDevice.DrawPrimitive(D3DPT_TRIANGLESTRIP, 16, 2 );
g_pd3dDevice.DrawPrimitive(D3DPT_TRIANGLESTRIP, 20, 2 );
g_pd3dDevice.EndScene;
g_pd3dDevice.Present(nil, nil, 0, nil);
end;
//-----------------------------------------------------------------------------
begin
ZeroMemory(@uMsg, SizeOf(MSG));
ZeroMemory(@winClass, SizeOf(WNDCLASSEX));
with winClass do
begin
lpszClassName := 'MY_WINDOWS_CLASS';
cbSize := SizeOf(WNDCLASSEX);
style := CS_HREDRAW or CS_VREDRAW;
lpfnWndProc := @WindowProc;
hInstance := hInstance;
hIcon := LoadIcon(hInstance, IDI_APPLICATION);
hIconSm := LoadIcon(hInstance, IDI_APPLICATION);
hCursor := LoadCursor(0, IDC_ARROW);
hbrBackground := $000000;
lpszMenuName := nil;
cbClsExtra := 0;
cbWndExtra := 0;
end;
if (RegisterClassEx(winClass) = 0) then
Halt(0);
g_hWnd := CreateWindowEx(0,
winClass.lpszClassName,
'Direct3D (DX9) - Vertex Data',
WS_OVERLAPPEDWINDOW or WS_VISIBLE,
0,
0,
640,
480,
0,
0,
winClass.hInstance,
nil);
if g_hWnd = 0 then
Halt(0);
ShowWindow(g_hWnd, SW_SHOW);
UpdateWindow(g_hWnd);
Init;
while (uMsg.message <> WM_QUIT) do
begin
if PeekMessage(uMsg, 0, 0, 0, PM_REMOVE) then
begin
TranslateMessage(uMsg);
DispatchMessage(uMsg);
end
else
begin
g_dCurrentTime := timeGetTime;
g_fElapsedTime := ((g_dCurrentTime - g_dLastTime) * 0.001);
g_dLastTime := g_dCurrentTime;
Render;
end;
end;
ShutDown;
UnregisterClass(winClass.lpszClassName, winClass.hInstance);
end.
-
Второй пример:
program dx9_transforms;
uses
Windows,
Messages,
MMSystem,
Direct3D9,
D3DX9;
type
TVertex = record
x, y, z : Single;
diffuse : Longword;
end;
const
D3DFVF_MY_VERTEX = D3DFVF_XYZ or D3DFVF_DIFFUSE;
var
g_hWnd : THandle = 0;
g_pD3D : IDirect3D9 = nil;
g_pd3dDevice : IDirect3DDevice9 = nil;
g_pSunMesh : ID3DXMesh = nil;
g_pEarthMesh : ID3DXMesh = nil;
g_pMoonMesh : ID3DXMesh = nil;
g_matrixStack : ID3DXMatrixStack = nil;
g_fElpasedTime : Single;
g_dCurrentTime : Longword;
g_dLastTime : Longword;
g_fSpeedmodifier : Single = 1.0;
g_bOrbitOn : Boolean = True;
g_fSunSpin : Single = 0.0;
g_fEarthSpin : Single = 0.0;
g_fEarthOrbit : Single = 0.0;
g_fMoonSpin : Single = 0.0;
g_fMoonOrbit : Single = 0.0;
winClass : WNDCLASSEX;
uMsg : MSG;
//---
function WindowProc(ihwnd: THandle; uMsg: Longword; wParam: Longint; lParam: Longint): Longint; stdcall;
begin
WindowProc := 0;
case uMsg of
WM_KEYDOWN: begin
case wParam of
VK_ESCAPE : PostQuitMessage(0);
VK_F1 : g_fSpeedmodifier := g_fSpeedmodifier + 1.0;
VK_F2 : g_fSpeedmodifier := g_fSpeedmodifier - 1.0;
VK_SPACE : g_bOrbitOn := not(g_bOrbitOn);
end;
end;
WM_CLOSE: PostQuitMessage(0);
WM_DESTROY: PostQuitMessage(0);
else WindowProc := DefWindowProc(ihwnd, uMsg, wParam, lParam);
end;
end;
//---
// Name: Init()
// Desc:
//---
procedure Init;
var
d3ddm : TD3DDisplayMode;
d3dpp : TD3DPresentParameters;
matProj : TD3DMatrix;
pTempEarthMesh : ID3DXMesh;
pTempSunMesh : ID3DXMesh;
pTempVertexBuffer : IDirect3DVertexBuffer9;
nNumVerts : Longword;
i : Longword;
pVertex : Pointer;
Vertex : array of TVertex;
begin
g_pD3D := Direct3DCreate9(D3D_SDK_VERSION);
g_pD3D.GetAdapterDisplayMode(D3DADAPTER_DEFAULT,
d3ddm);
ZeroMemory(@d3dpp, SizeOf(TD3DPresentParameters));
with d3dpp do
begin
Windowed := True;
SwapEffect := D3DSWAPEFFECT_DISCARD;
BackBufferFormat := d3ddm.Format;
EnableAutoDepthStencil := True;
AutoDepthStencilFormat := D3DFMT_D16;
PresentationInterval := D3DPRESENT_INTERVAL_IMMEDIATE;
end;
g_pD3D.CreateDevice(D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL,
g_hWnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
@d3dpp,
g_pd3dDevice);
g_pd3dDevice.SetRenderState(D3DRS_LIGHTING, iFalse);
g_pd3dDevice.SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
g_pd3dDevice.SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME);
D3DXMatrixPerspectiveFovLH(matProj,
D3DXToRadian(45.0),
(640 / 480),
0.1,
100.0);
g_pd3dDevice.SetTransform(D3DTS_PROJECTION, matProj);
// We'll use the D3DXCreateSphere utility function to create three simple
D3DXCreateSphere(g_pd3dDevice, 1.0, 20, 20, pTempSunMesh, nil);
D3DXCreateSphere(g_pd3dDevice, 1.0, 10, 10, pTempEarthMesh, nil);
D3DXCreateSphere(g_pd3dDevice, 0.5, 8, 8, g_pMoonMesh, nil);
// using a FVF code that does include color so we can set up the Earth
// and Sun with color.
//
// Once that's been done, we'll need to set the color values to something
pTempVertexBuffer := nil;
pTempEarthMesh.CloneMeshFVF(0, D3DFVF_MY_VERTEX, g_pd3dDevice, g_pEarthMesh);
if Succeeded(g_pEarthMesh.GetVertexBuffer(pTempVertexBuffer)) then
begin
nNumVerts := g_pEarthMesh.GetNumVertices;
pVertex := nil;
SetLength(Vertex, nNumVerts);
pTempVertexBuffer.Lock(0, 0, pVertex, 0);
Move(pVertex^, Vertex[0], nNumVerts * SizeOf(TVertex));
for i := 0 to (nNumVerts - 1) do
Vertex[i].diffuse := D3DCOLOR_COLORVALUE(0.0, 0.0, 1.0, 1.0);
Move(Vertex[0], pVertex^, nNumVerts * SizeOf(TVertex));
pTempVertexBuffer.Unlock;
pTempVertexBuffer._Release
pTempVertexBuffer := nil;
SetLength(Vertex, 0);
end;
pTempSunMesh.CloneMeshFVF(0, D3DFVF_MY_VERTEX, g_pd3dDevice, g_pSunMesh);
if Succeeded(g_pSunMesh.GetVertexBuffer(pTempVertexBuffer)) then
begin
nNumVerts := g_pSunMesh.GetNumVertices;
pVertex := nil;
SetLength(Vertex, nNumVerts);
pTempVertexBuffer.Lock(0, 0, pVertex, 0);
Move(pVertex^, Vertex[0], nNumVerts * SizeOf(TVertex));
for i := 0 to (nNumVerts - 1) do
Vertex[i].diffuse := D3DCOLOR_COLORVALUE(1.0, 1.0, 0.0, 1.0);
Move(Vertex[0], pVertex^, nNumVerts * SizeOf(TVertex));
pTempVertexBuffer.Unlock;
pTempVertexBuffer._Release
pTempVertexBuffer := nil;
end;
pTempEarthMesh._Release;
pTempEarthMesh := nil;
pTempSunMesh._Release;
pTempSunMesh := nil;
D3DXCreateMatrixStack(0, g_matrixStack);
end;
-
Продолжение кода:
procedure ShutDown;
begin
if Assigned(g_matrixStack) then
begin
g_matrixStack._Release;
g_matrixStack := nil;
end;
if Assigned(g_pSunMesh) then
begin
g_pSunMesh._Release;
g_pSunMesh := nil;
end;
if Assigned(g_pEarthMesh) then
begin
g_pEarthMesh._Release;
g_pEarthMesh := nil;
end;
if Assigned(g_pMoonMesh) then
begin
g_pMoonMesh._Release;
g_pMoonMesh := nil;
end;
if Assigned(g_pd3dDevice) then
begin
g_pd3dDevice._Release;
g_pd3dDevice := nil;
end;
if Assigned(g_pD3D) then
begin
g_pD3D._Release;
g_pD3D := nil;
end;
end;
procedure Render;
var
matView : TD3DMatrix;
mSunScale : TD3DMatrix;
mSunSpinRotation : TD3DMatrix;
mSunMatrix : TD3DMatrix;
mEarthTranslationToOrbit : TD3DMatrix;
mEarthSpinRotation : TD3DMatrix;
mEarthOrbitRotation : TD3DMatrix;
mEarthMatrix : TD3DMatrix;
mMoonTranslationToOrbit : TD3DMatrix;
mMoonSpinRotation : TD3DMatrix;
mMoonOrbitRotation : TD3DMatrix;
mMoonMatrix : TD3DMatrix;
begin
if g_pd3dDevice = nil then Exit;
g_pd3dDevice.Clear(0,
nil,
D3DCLEAR_TARGET or D3DCLEAR_ZBUFFER,
D3DCOLOR_COLORVALUE(0.0, 0.0, 0.0, 1.0),
1.0,
0);
g_pd3dDevice.BeginScene;
D3DXMatrixLookAtLH(matView,
D3DXVector3(0.0, 2.0, -25.0), D3DXVector3(0.0, 0.0, 0.0), D3DXVector3(0.0, 1.0, 0.0));
g_pd3dDevice.SetTransform(D3DTS_VIEW, matView);
if g_bOrbitOn then
begin
g_fSunSpin := g_fSunSpin + (g_fSpeedmodifier * (g_fElpasedTime * 10.0));
g_fEarthSpin := g_fEarthSpin + (g_fSpeedmodifier * (g_fElpasedTime * 100.0));
g_fEarthOrbit := g_fEarthOrbit + (g_fSpeedmodifier * (g_fElpasedTime * 20.0));
g_fMoonSpin := g_fMoonSpin + (g_fSpeedmodifier * (g_fElpasedTime * 50.0));
g_fMoonOrbit := g_fMoonOrbit + (g_fSpeedmodifier * (g_fElpasedTime * 200.0));
end;
D3DXMatrixRotationY(mSunSpinRotation, D3DXToRadian(g_fSunSpin));
D3DXMatrixScaling(mSunScale, 5.0, 5.0, 5.0);
D3DXMatrixMultiply(mSunMatrix, mSunScale, mSunSpinRotation);
g_pd3dDevice.SetTransform(D3DTS_WORLD, mSunMatrix);
g_pSunMesh.DrawSubset(0);
D3DXMatrixRotationY(mEarthSpinRotation, D3DXToRadian(g_fEarthSpin));
D3DXMatrixTranslation(mEarthTranslationToOrbit, 0.0, 0.0, 12.0);
D3DXMatrixRotationY(mEarthOrbitRotation, D3DXToRadian(g_fEarthOrbit));
// 3. and rotate it again to make it orbit the origin (or the Sun).
//
D3DXMatrixMultiply(mEarthMatrix, mEarthSpinRotation, mEarthTranslationToOrbit);
D3DXMatrixMultiply(mEarthMatrix, mEarthMatrix, mEarthOrbitRotation);
g_pd3dDevice.SetTransform(D3DTS_WORLD, mEarthMatrix);
g_pEarthMesh.DrawSubset(0);
//
// The Moon is the hardest to understand since it needs to not only spin on
// its own axis and orbit the Earth, but needs to follow the Earth,
// which is orbiting the Sun.
//
// This can be done by combining five transformations together with the last
// two being borrowed from the Earth's transformation.
D3DXMatrixRotationY(mMoonSpinRotation, D3DXToRadian(g_fMoonSpin));
D3DXMatrixRotationY(mMoonOrbitRotation, D3DXToRadian(g_fMoonOrbit));
D3DXMatrixTranslation(mMoonTranslationToOrbit, 0.0, 0.0, 2.0);
// that it is, we can set up the Moon just like the we did the Earth since
// the Moon orbits the Earth just like the Earth orbits the Sun.
//
// Once the Moon's transforms are set up we simply reuse the Earth's
D3DXMatrixMultiply(mMoonMatrix, mMoonSpinRotation, mMoonTranslationToOrbit);
D3DXMatrixMultiply(mMoonMatrix, mMoonMatrix, mMoonOrbitRotation);
D3DXMatrixMultiply(mMoonMatrix, mMoonMatrix, mEarthTranslationToOrbit);
D3DXMatrixMultiply(mMoonMatrix, mMoonMatrix, mEarthOrbitRotation);
g_pd3dDevice.SetTransform(D3DTS_WORLD, mMoonMatrix);
g_pMoonMesh.DrawSubset(0);
g_pd3dDevice.EndScene;
g_pd3dDevice.Present(nil, nil, 0, nil);
end;
-
Продолжение, второй вариант процедуры рендера: s at)
D3DXMatrixMultiply(mEarthMatrix, mEarthSpinRotation, mEarthTranslationToOrbit);
D3DXMatrixMultiply(mEarthMatrix, mEarthMatrix, mEarthOrbitRotation);
g_matrixStack.Push;
g_matrixStack.MultMatrixLocal(mEarthMatrix);
g_pd3dDevice.SetTransform(D3DTS_WORLD, g_matrixStack.GetTop^);
g_pEarthMesh.DrawSubset(0);
g_matrixStack.Pop;
//
D3DXMatrixRotationY(mMoonSpinRotation, D3DXToRadian(g_fMoonSpin));
D3DXMatrixRotationY(mMoonOrbitRotation, D3DXToRadian(g_fMoonOrbit));
D3DXMatrixTranslation(mMoonTranslationToOrbit, 0.0, 0.0, 2.0);
//
// The key to understanding the first three transforms is to pretend that
// the Earth is located at the origin. We know it's not, but if we pretend
D3DXMatrixMultiply(mMoonMatrix, mMoonSpinRotation, mMoonTranslationToOrbit);
D3DXMatrixMultiply(mMoonMatrix, mMoonMatrix, mMoonOrbitRotation);
D3DXMatrixMultiply(mMoonMatrix, mMoonMatrix, mEarthTranslationToOrbit);
D3DXMatrixMultiply(mMoonMatrix, mMoonMatrix, mEarthOrbitRotation);
g_matrixStack.Push;
g_matrixStack.MultMatrixLocal(mMoonMatrix);
g_pd3dDevice.SetTransform(D3DTS_WORLD, g_matrixStack.GetTop^);
g_pMoonMesh.DrawSubset(0);
g_matrixStack.Pop;
g_pd3dDevice.EndScene;
g_pd3dDevice.Present(nil, nil, 0, nil);
end;
*)
-
Завершение второго примера:
//-----------------------------------------------------------------------------
begin
ZeroMemory(@uMsg, SizeOf(MSG));
ZeroMemory(@winClass, SizeOf(WNDCLASSEX));
with winClass do
begin
lpszClassName := 'MY_WINDOWS_CLASS';
cbSize := SizeOf(WNDCLASSEX);
style := CS_HREDRAW or CS_VREDRAW;
lpfnWndProc := @WindowProc;
hInstance := hInstance;
hIcon := LoadIcon(hInstance, IDI_APPLICATION);
hIconSm := LoadIcon(hInstance, IDI_APPLICATION);
hCursor := LoadCursor(0, IDC_ARROW);
hbrBackground := $000000;
lpszMenuName := nil;
cbClsExtra := 0;
cbWndExtra := 0;
end;
if (RegisterClassEx(winClass) = 0) then
Halt(0);
g_hWnd := CreateWindowEx(0,
winClass.lpszClassName,
'Direct3D (DX9) - Transforms',
WS_OVERLAPPEDWINDOW or WS_VISIBLE,
0,
0,
640,
480,
0,
0,
winClass.hInstance,
nil);
if g_hWnd = 0 then
Halt(0);
ShowWindow(g_hWnd, SW_SHOW);
UpdateWindow(g_hWnd);
Init;
g_dLastTime := timeGetTime;
while (uMsg.message <> WM_QUIT) do
begin
if PeekMessage(uMsg, 0, 0, 0, PM_REMOVE) then
begin
TranslateMessage(uMsg);
DispatchMessage(uMsg);
end
else
begin
g_dCurrentTime := timeGetTime;
g_fElpasedTime := ((g_dCurrentTime - g_dLastTime) * 0.001);
g_dLastTime := g_dCurrentTime;
Render;
end;
end;
ShutDown;
UnregisterClass(winClass.lpszClassName, winClass.hInstance);
end.
-
Должны были вращаться так, чтобы первый (который вначале ближе к нам) перекрывался потом вторым. Решение оказалось простым, когда я посмотрел другие примеры и сравнил с этим кодом: надо было Z-буффер поставить :) Так привый к OpenGL'ю, в котором это делается не задумываясь, что забыл совсем
|