{{notification.text}}

MirGames

nneo
28.03.12 23:49
0
Здравствуйте. Directx и Delphi. У меня на форме выводится трехмерный объект, камеру можно вращать правой клавишей мыши. Мне нужно по щелчку левой кнопкой мыши по объекту мировые координаты вершины объекта в которую я ткнул. Для этого в обработчике нажатия левой кнопки мыши я в цикле прогоняю все вершины объекта через D3DXVec3Project и сравниваю полученные экранные координаты с фактическими и если они совпадают, то окрашиваю эту вершину и близлежащие в черный цвет. Проблема в том, что окрашиваются совсем не те вершины, в которые я тычу мышью, из-за того что D3DXVec3Project выдает не верные экранные координаты, а если покрутить камеру, то все еще хуже - вообще не красит никакие вершины, хотя щелкаю по объекту. Перерыл кучу форумов, но так и не разобрался с проблемой, если кто-нибудь сталкивался с этим, прошу помогите.

Код инициализации:
function TForm1.Init;
var
l_D3DPresentParameters: TD3DPresentParameters;
d3ddm : TD3DDISPLAYMODE;
matProj : TD3DMatrix;
begin
Result:= E_FAIL;
g_D3DObject := Direct3DCreate9(D3D_SDK_VERSION);
g_D3DObject.GetAdapterDisplayMode(D3DADAPTER_DEFAULT, d3ddm);
if (g_D3DObject = nil) then Exit;
FillChar(l_D3DPresentParameters, SizeOf(l_D3DPresentParameters), 0);
with l_D3DPresentParameters do
begin
Windowed := True;
SwapEffect := D3DSWAPEFFECT_DISCARD;
BackBufferFormat := d3ddm.Format;
EnableAutoDepthStencil := True;
AutoDepthStencilFormat := D3DFMT_D24X8;
PresentationInterval := D3DPRESENT_INTERVAL_IMMEDIATE;
end;
Result := g_D3DObject.CreateDevice(
D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL,
Handle,
D3DCREATE_HARDWARE_VERTEXPROCESSING,
@l_D3DPresentParameters,
g_Device
);
g_Device.SetRenderState(D3DRS_LIGHTING, iFalse);
g_Device.SetRenderState(D3DRS_ZENABLE, iTrue);
g_Device.SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
D3DXMatrixPerspectiveFovLH(matProj,
D3DXToRadian(45.0),
(ClientWidth/ClientHeight),
0.1,
10000.0);
g_Device.SetTransform(D3DTS_PROJECTION, matProj);
if FAILED(Result) then
begin
g_D3DObject := nil;
Exit;
end;
Result := S_OK;
end;


Рендер: procedure TForm1.Timer(Sender: TObject; var Done: Boolean);
var
matTrans : TD3DMatrix;
matRot : TD3DMatrix;
//matWorld : TD3DMatrix;
begin
if ToDraw then
begin
Done := false;
g_Device.Clear(0, nil, D3DCLEAR_TARGET or D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(230, 230, 230), 1.0, 0);
g_Device.SetRenderState(D3DRS_ZENABLE, iTRUE);
g_Device.SetRenderState(D3DRS_ZWRITEENABLE, iTRUE);
g_Device.SetRenderState(D3DRS_ALPHABLENDENABLE, iFALSE);
D3DXMatrixTranslation(matTrans, g_trX, g_trY, g_trZ);
D3DXMatrixRotationYawPitchRoll(matRot,
D3DXToRadian(g_fSpinX),
D3DXToRadian(g_fSpinY),
//-pi/2);
0);
D3DXMatrixMultiply(matWorld, matRot, matTrans);
g_Device.SetTransform(D3DTS_WORLD, matWorld);
g_Device.BeginScene;
if FileLoaded then
begin
g_Device.SetStreamSource(0, g_VB, 0, sizeof(TVertex));
g_Device.SetFVF(FVF);
g_Device.DrawPrimitive(
D3DPT_TRIANGLELIST, 0,
(FN-1)*(FM-1)*2
);
end;
g_Device.EndScene;
g_Device.Present(nil, nil, 0, nil);
end;
end;



Обработчик нажатия мышки: procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
var
v, OutP0, OutP1, vOut : D3DVECTOR;
i, j, k : integer;
begin
if Button=mbRight then
begin
g_ptCurrentMousePosit.X := X;
g_ptCurrentMousePosit.Y := Y;
g_ptLastMousePosit := g_ptCurrentMousePosit;
g_bMousing := True;
end;
if Button=mbLeft then
begin
g_Device.GetViewport(Viewport);
g_Device.GetTransform(D3DTS_PROJECTION, matProjection);
g_Device.GetTransform(D3DTS_VIEW, matView);
g_Device.GetTransform(D3DTS_WORLD, matWorld);
for i := 0 to Length(Vertices) - 1 do
begin
v.x:=Vertices[i].x;
v.y:=Vertices[i].y;
v.z:=Vertices[i].z;
D3DXVec3Project(OutP0, v, Viewport, matProjection, matView, matWorld);
if CompareValue(OutP0.y, Y, 5)=0 then
begin
OutP1.y:=v.y;
break;
end;
end;
i:=Poisk(YPoints[0], 2*OutP1.y, 0, Length(YPoints[0])-1);
if Length(TempCol)>0 then
for j := 0 to FN - 1 do
begin
RCol[j,Tempi].r:=TempCol[j].r;
RCol[j,Tempi].g:=TempCol[j].g;
RCol[j,Tempi].b:=TempCol[j].b;
end;
Tempi:=i;
SetLength(TempCol, FN);
for j := 0 to FN - 1 do
begin
TempCol[j].r:=RCol[j,Tempi].r;
TempCol[j].g:=RCol[j,Tempi].g;
TempCol[j].b:=RCol[j,Tempi].b;
RCol[j,Tempi].r:=0;
RCol[j,Tempi].g:=0;
RCol[j,Tempi].b:=0;
end;
k:=0;
for j :=0 to FM - 2 do
for i := 0 to FN - 2 do
begin
Vertices[k].color:=RGB(RCol[i,j].b,RCol[i,j].g,RCol[i,j].r);
k:=k+1;
Vertices[k].color:=RGB(RCol[i,j+1].b,RCol[i,j+1].g,RCol[i,j+1].r);
k:=k+1;
Vertices[k].color:=RGB(RCol[i+1,j].b,RCol[i+1,j].g,RCol[i+1,j].r);
k:=k+1;
Vertices[k].color:=RGB(RCol[i+1,j].b,RCol[i+1,j].g,RCol[i+1,j].r);
k:=k+1;
Vertices[k].color:=RGB(RCol[i+1,j+1].b,RCol[i+1,j+1].g,RCol[i+1,j+1].r);
k:=k+1;
Vertices[k].color:=RGB(RCol[i,j+1].b,RCol[i,j+1].g,RCol[i,j+1].r);
k:=k+1;
end;
g_VB.Lock(0, sizeof(TVertex)*Length(Vertices), pVertices, 0);
Move(Vertices[0], pVertices^, sizeof(TVertex)*Length(Vertices));
g_VB.Unlock;
end;
end;
#1
Dan
The One
29.03.12 00:34
0
D3DXVec3Project(OutP0, v, Viewport, matProjection, matView, matWorld);
выглядит верно, скорее всего ошибка в другом месте. попробуй отрисовать все проецированые вершины на экран, чтобы убедиться что ошибка именно в проецировании, а не где-то ещё.
#{{post.Index}}
{{post.Author.Login}}
{{post.CreatedDate | date:'dd.MM.yy HH:mm'}}
{{post.VotesRating}}
Отредактировано: {{post.UpdatedDate | date:'dd.MM.yy HH:mm'}}