![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Проблема с камерой [Delphi, Windows]
ElectriC © (2007-04-18 21:20:00)Есть проблемка с камерой: Допустим, когда начинаешь вертеть мышкой по/против часовой стрелки, камера, как и положено поворачивается вверх/вниз/влево/вправо, но при этом она ещё начинает переворачивается по/против часовой стрелки? Не подскажите, в чём проблем-ка.
P.S. Или посоветуйте что нужно улучшить.
Код движение камеры мышкой:
...
Xi, Yi : Single;
Cursor : TPoint
...
GetCursorPos(Cursor);
SetCursorPos(800 div 2, 600 div 2);
Xi := Xi + (Cursor.X - 400)/100 * 0.1;
Yi := Yi - (300 - Cursor.Y)/100 * 0.1;
RotateLR(Xi);
RotateUD(Yi);
Xi := 0; Yi := 0;
...
Код модуля камеры:
SLCamera = packed record
CameraType : (FP, FREE);//камера для первого лица/свободная камера
View, Proj : TD3DMatrix;
Xi, Yi : Single;
LR, UD,
LK, PS : TD3DXVECTOR3;
end;
var D3DDevice : IDirect3DDevice9;
procedure GetViewMatrix;
var X, Y, Z : Single;
begin
with SLCamera do
begin
D3DXVec3Normalize(LK, LK);
D3DXVec3Cross (UD, LK, LR);
D3DXVec3Normalize(UD, UD);
D3DXVec3Cross (LR, UD, LK);
D3DXVec3Normalize(LR, LR);
X := -D3DXVec3Dot(LR, PS);
Y := -D3DXVec3Dot(UD, PS);
Z := -D3DXVec3Dot(LK, PS);
with View do
begin
m[0, 0] := LR.x;
m[0, 1] := UD.x;
m[0, 2] := LK.x;
m[0, 3] := 0.0;
m[1, 0] := LR.y;
m[1, 1] := UD.y;
m[1, 2] := LK.y;
m[1, 3] := 0.0;
m[2, 0] := LR.z;
m[2, 1] := UD.z;
m[2, 2] := LK.z;
m[2, 3] := 0.0;
m[3, 0] := X;
m[3, 1] := Y;
m[3, 2] := Z;
m[3, 3] := 1.0;
end;
D3DDevice.SetTransform(D3DTS_VIEW, View);
D3DXMatrixPerspectiveFovLH(Proj, D3DX_PI / 4, 1.0, 1.0, 1000.0);
D3DDevice.SetTransform(D3DTS_PROJECTION, Proj);
end;
end;
{ движение влево/вправо }
procedure MoveLR(Step : Single);
begin
with SLCamera do
case CameraType of
FP : PS := D3DXVECTOR3(PS.x + LR.x * Step, 0.0,
PS.z + LR.z * Step);
FREE : PS := D3DXVECTOR3(PS.x + LR.x * Step, PS.y + LR.y * Step,
PS.z + LR.z * Step);
end;
GetViewMatrix;
end;
{ движение вверх/вниз }
procedure MoveUD(Step : Single);
begin
with SLCamera do
If CameraType = FREE then
begin
PS.x := PS.x + UD.x * Step;
PS.y := PS.y + UD.y * Step;
PS.z := PS.z + UD.z * Step;
end;
GetViewMatrix;
end;
{ движение вперёд/назад }
procedure MoveFB(Step : Single);
begin
with SLCamera do
case CameraType of
FP : PS := D3DXVECTOR3(PS.x + LK.x * Step, 0.0, PS.z + LK.z * Step);
FREE : begin
PS.x := PS.x + LK.x * Step;
PS.y := PS.y + LK.y * Step;
PS.z := PS.z + LK.z * Step;
end;
end;
GetViewMatrix;
end;
{ поаорот влево/вправо }
procedure RotateLR(Step : Single);
var Mat : TD3DXMatrix;
begin
with SLCamera do
begin
case CameraType of
FP : D3DXMatrixRotationY (Mat, Step);
FREE : D3DXMatrixRotationAxis(Mat, UD, Step);
end;
D3DXVec3TransformCoord(LR, LR, Mat);
D3DXVec3TransformCoord(LK, LK, Mat);
end;
GetViewMatrix;
end;
{ поворот вверх/вниз }
procedure RotateUD(Step : Single);
var Mat : TD3DXMatrix;
begin
with SLCamera do
begin
D3DXMatrixRotationAxis(Mat, LR, Step);
D3DXVec3TransformCoord( UD, UD, Mat);
D3DXVec3TransformCoord( LK, LK, Mat);
end;
GetViewMatrix;
end;
{ поворот по/против часовой стрелки }
procedure RotateUC(Step : Single);
var Mat : TD3DXMatrix;
begin
with SLEngine.SLCamera do
If CameraType = FREE then
begin
D3DXMatrixRotationAxis(Mat, LK, Step);
D3DXVec3TransformCoord( LR, LR, Mat);
D3DXVec3TransformCoord( UD, UD, Mat);
end;
GetViewMatrix;
end;
end.
ElectriC (2007-04-30 11:29:00) [1]А, всё!!! Въехал наконец-то)))
ElectriC (2007-04-29 23:05:00) [2]Лучше, наверное, будет этот код (и он тож не работает):
procedure Axis(Step : Single);
var matTrans, matRot, matWorld : TD3DXMatrix;
begin
D3DXMatrixTranslation(matTrans, 0.0, 0.0, 10.0);
D3DXMatrixRotationYawPitchRoll(matRot,
D3DXToRadian(Step),
0.0,
0.0);
matWorld.m[0, 0] := matRot.m[0, 0] * matTrans.m[0, 0];
matWorld.m[0, 1] := matRot.m[0, 1] * matTrans.m[0, 1];
matWorld.m[0, 2] := matRot.m[0, 2] * matTrans.m[0, 2];
matWorld.m[0, 3] := matRot.m[0, 3] * matTrans.m[0, 3];
matWorld.m[1, 0] := matRot.m[1, 0] * matTrans.m[1, 0];
matWorld.m[1, 1] := matRot.m[1, 1] * matTrans.m[1, 1];
matWorld.m[1, 2] := matRot.m[1, 2] * matTrans.m[1, 2];
matWorld.m[1, 3] := matRot.m[1, 3] * matTrans.m[1, 3];
matWorld.m[2, 0] := matRot.m[2, 0] * matTrans.m[2, 0];
matWorld.m[2, 1] := matRot.m[2, 1] * matTrans.m[2, 1];
matWorld.m[2, 2] := matRot.m[2, 2] * matTrans.m[2, 2];
matWorld.m[2, 3] := matRot.m[2, 3] * matTrans.m[2, 3];
matWorld.m[3, 0] := matRot.m[3, 0] * matTrans.m[3, 0];
matWorld.m[3, 1] := matRot.m[3, 1] * matTrans.m[3, 1];
matWorld.m[3, 2] := matRot.m[3, 2] * matTrans.m[3, 2];
matWorld.m[3, 3] := matRot.m[3, 3] * matTrans.m[3, 3];
Device.SetTransform(D3DTS_WORLD, matWorld);
end;
end;
Пробовал изменять Device.SetTransform(D3DTS_WORLD, matWorld) на
Device.SetTransform(D3DTS_VIEW, matWorld) => Объекты вообще исчезают(((
ElectriC (2007-04-29 21:51:00) [3]Я понял, что надо так (хотя и не работает):
LK : TD3DXVECTOR3;
procedure Axis(Step : Single);
var Mat : TD3DXMatrix;
begin
D3DXMatrixRotationAxis(Mat, LK, Step);
D3DXMatrixTranslation (Mat, Step, 0.0, 0.0);
D3DXMatrixMultiply (Mat, Mat, Mat);
Device.SetTransform ( D3DTS_VIEW, Mat);
end;
Или нет?
Sapersky (2007-04-20 18:44:00) [4]Нет у меня конкретной процедуры, нужно выдирать куски из разных мест, а это долго.
Умножаешь матрицы в правильном порядке? Т.е. порядок передачи параметров в функцию имеет значение.
И чем всё-таки CD3DArcBall не угодил? Хотя в примерах SDK он в основном применяется к матрице модели, фактически можно применять и к видовой. Рекомендация глобального характера - см. ветку про текстуры, качай книги по ссылкам, читай.
ElectriC (2007-04-20 18:17:00) [5]...
ElectriC (2007-04-20 15:04:00) [6]Чё т не выходит! Так можешь написать исходник процедуры, которая ворочает камеру вокруг точки, плиз!
ElectriC (2007-04-20 00:32:00) [7]Спасибо, по-экспериментируем))
Sapersky (2007-04-19 21:10:00) [8]Я так понял, что в [0] как раз и есть вращение камеры вокруг объекта (толком не вникал), а проблема в том, чтобы сделать вращение относительно произвольной точки.
Если нет... можно заранее подготовить видовую матрицу, направленную в 0 (тем же GetViewMatrix) и потом умножать её на матрицу вращения, полученную D3DXMatrixRotationAxis.
Матрица перемещения - D3DXMatrixTranslation. Потом ещё раз D3DXMatrixMultiply, потом SetTransform(D3DTS_VIEW, ...).
ElectriC (2007-04-19 19:52:00) [9]Можешь написать исходный текст?
Sapersky (2007-04-19 19:27:00) [10]Обычно формируют матрицу вращения относительно 0-й точки, потом умножают её на матрицу перемещения в точку, относительно которой нужно крутить.
Правда, в моём тесте для достижения нужного результата пришлось перемещать в обратном направлении. То ли у меня что-то напутано, то ли действительно так и есть.
ElectriC (2007-04-19 15:57:00) [11]Понятно!
Последний вопрос: Как сделать поворот камеры вокруг какого-либо объекта,
например дома, как это сделано, допустим, в Sims'ах?
P.S. Использование нмжеприведённого кода не предлагать:
RotateLR( 0.02);
MoveLR (-0.02);
если ошибаюсь, то
RotateLR(-0.02);
MoveLR ( 0.02);
Sapersky (2007-04-19 14:23:00) [12]В примерах к DX SDK не вращается - видимо из-за того, что вращение там делается через кватернионы. В DX8 это класс D3DUtil.CD3DArcBall.
В принципе, само по себе вращение не порок, оно присутствует в некоторых коммерческих CAD, например. Даже логично - крутим мышкой вокруг объекта -> поворачиваем объект относительно перпендикулярной экрану оси.